Compare commits

..

4 Commits

18 changed files with 247 additions and 338 deletions

View File

@ -5,7 +5,16 @@
[ [
./hardware-configuration.nix ./hardware-configuration.nix
../../modules/bootstrap.nix ../../modules/bootstrap.nix
../../builds/gmail_mail_bridge.nix
./radicale.nix
./ssh.nix
./gitea.nix
./radicale.nix
./vaultwarden.nix
./sslh.nix
./rss2email.nix
./fail2ban.nix
./nginx.nix
]; ];
# nix optimization # nix optimization
@ -14,7 +23,6 @@
dates = [ "03:45" ]; dates = [ "03:45" ];
}; };
networking.networkmanager.enable = true;
time.timeZone = "America/Chicago"; time.timeZone = "America/Chicago";
@ -35,100 +43,14 @@
neovim neovim
]; ];
services.gmail_mail_bridge.enable = true; system = {
copySystemConfiguration = true;
system.copySystemConfiguration = true; stateVersion = "23.05"; # don't change this, lol
system.stateVersion = "23.05"; # don't change this, lol
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/vda";
services.sslh = {
enable = true;
settings.protocols = [
{
host = "localhost";
name = "ssh";
port = "55555";
service = "ssh";
}
{
host = "localhost";
name = "tls";
port = "442";
}
];
}; };
networking.hostName = "netbox"; boot.loader = {
grub.enable = true;
services.radicale = { grub.device = "/dev/vda";
enable = true;
settings = {
auth = {
type = "htpasswd";
htpasswd_filename = "radicale-passwd";
htpasswd_encryption = "plain";
};
};
};
services.rss2email = {
enable = true;
to = "ryan@beepboop.systems";
feeds = {
"eff" = {
url = "https://www.eff.org/rss/updates.xml";
};
"nixos" = {
url = "https://nixos.org/blog/announcements-rss.xml";
};
"drewdevault" = {
url = "https://drewdevault.com/blog/index.xml";
};
"nullprogram" = {
url = "https://nullprogram.com/feed/";
};
};
};
services.fail2ban = {
enable = true;
ignoreIP = [
"192.168.1.0/24"
];
extraPackages = [pkgs.ipset];
banaction = "iptables-ipset-proto6-allports";
jails = {
"nginx-bruteforce" = ''
enabled = true
filter = nginx-bruteforce
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 6
findtime = 600
'';
"postfix-bruteforce" = ''
enabled = true
filter = postfix-bruteforce
maxretry = 6
findtime = 600
'';
};
};
environment.etc = {
"fail2ban/filter.d/nginx-bruteforce.conf".text = ''
[Definition]
failregex = ^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$
'';
"fail2ban/filter.d/postfix-bruteforce.conf".text = ''
[Definition]
failregex = warning: [\w\.\-]+\[<HOST>\]: SASL LOGIN authentication failed.*$
journalmatch = _SYSTEMD_UNIT=postfix.service
'';
}; };
users.users.ryan = { users.users.ryan = {
@ -141,127 +63,14 @@
extraGroups = [ "wheel" "docker" ]; extraGroups = [ "wheel" "docker" ];
}; };
services.openssh = { networking = {
enable = true; usePredictableInterfaceNames = false;
ports = [55555]; networkmanager.enable = true;
settings = { hostName = "netbox";
X11Forwarding = false;
PermitRootLogin = "no"; firewall = {
PasswordAuthentication = false; enable = true;
allowedTCPPorts = [ 80 443 ];
}; };
}; };
services.vaultwarden.enable = true;
services.vaultwarden.config = {
DOMAIN = "https://bitwarden.beepboop.systems";
SIGNUPS_ALLOWED = false;
};
networking.usePredictableInterfaceNames = false;
services.gitea = {
enable = true;
appName = "beepboop.systems"; # Give the site a name
database = {
type = "postgres";
passwordFile = "/etc/gittea-pass";
};
settings.security.INSTALL_LOCK = true;
settings.service = {
SHOW_REGISTRATION_BUTTON = false;
DISABLE_REGISRATION = true;
};
settings.ui.DEFAULT_THEME = "arc-green";
settings.api.ENABLE_SWAGGER = false;
settings.server = {
DOMAIN = "git.beepboop.systems";
ROOT_URL = "https://git.beepboop.systems/";
LANDING_PAGE = "explore";
HTTP_PORT = 3001;
};
};
services.postgresql = {
enable = true; # Ensure postgresql is enabled
authentication = ''
local gitea all ident map=gitea-users
'';
identMap = # Map the gitea user to postgresql
''
gitea-users gitea gitea
'';
};
services.nginx.enable = true;
services.nginx.clientMaxBodySize = "100m";
services.nginx.defaultSSLListenPort = 442;
services.nginx.virtualHosts."beepboop.systems" = {
forceSSL = true;
enableACME = true;
root = "/var/www/beepboop.systems";
locations."/" = {
extraConfig = ''
port_in_redirect off;
absolute_redirect off;
'';
};
};
services.nginx.virtualHosts."git.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:3001";
};
};
services.nginx.virtualHosts."bit.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "bitwarden.beepboop.systems";
};
services.nginx.virtualHosts."bitwarden.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8000";
};
};
services.nginx.virtualHosts."radicale.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5232";
extraConfig = ''
proxy_set_header X-Script-Name /;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Authorization;
'';
};
};
services.nginx.virtualHosts."calendar.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
services.nginx.virtualHosts."cal.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
security.acme = {
acceptTerms = true;
defaults.email = "nickforanick@protonmail.com";
};
networking.firewall = {
enable = true;
allowedTCPPorts = [ 80 443 ];
};
} }

42
boxes/netbox/fail2ban.nix Normal file
View File

@ -0,0 +1,42 @@
{ lib, config, pkgs, ... }:
{
services.fail2ban = {
enable = true;
ignoreIP = [
"192.168.1.0/24"
];
extraPackages = [pkgs.ipset];
banaction = "iptables-ipset-proto6-allports";
jails = {
"nginx-bruteforce" = ''
enabled = true
filter = nginx-bruteforce
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 6
findtime = 600
'';
"postfix-bruteforce" = ''
enabled = true
filter = postfix-bruteforce
maxretry = 6
findtime = 600
'';
};
};
environment.etc = {
"fail2ban/filter.d/nginx-bruteforce.conf".text = ''
[Definition]
failregex = ^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$
'';
"fail2ban/filter.d/postfix-bruteforce.conf".text = ''
[Definition]
failregex = warning: [\w\.\-]+\[<HOST>\]: SASL LOGIN authentication failed.*$
journalmatch = _SYSTEMD_UNIT=postfix.service
'';
};
}

43
boxes/netbox/gitea.nix Normal file
View File

@ -0,0 +1,43 @@
{ lib, config, pkgs, ... }:
{
services.gitea = {
enable = true;
appName = "beepboop.systems"; # Give the site a name
database = {
type = "postgres";
passwordFile = "/etc/gittea-pass";
};
settings.security.INSTALL_LOCK = true;
settings.service = {
SHOW_REGISTRATION_BUTTON = false;
DISABLE_REGISRATION = true;
};
settings.ui.DEFAULT_THEME = "arc-green";
settings.api.ENABLE_SWAGGER = false;
settings.server = {
DOMAIN = "git.beepboop.systems";
ROOT_URL = "https://git.beepboop.systems/";
LANDING_PAGE = "explore";
HTTP_PORT = 3001;
};
};
services.postgresql = {
enable = true; # Ensure postgresql is enabled
authentication = ''
local gitea all ident map=gitea-users
'';
identMap = # Map the gitea user to postgresql
''
gitea-users gitea gitea
'';
};
services.nginx.virtualHosts."git.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:3001";
};
};
}

23
boxes/netbox/nginx.nix Normal file
View File

@ -0,0 +1,23 @@
{ lib, config, pkgs, ... }:
{
services.nginx.enable = true;
services.nginx.clientMaxBodySize = "100m";
services.nginx.defaultSSLListenPort = 442;
services.nginx.virtualHosts."beepboop.systems" = {
forceSSL = true;
enableACME = true;
root = "/var/www/beepboop.systems";
locations."/" = {
extraConfig = ''
port_in_redirect off;
absolute_redirect off;
'';
};
};
security.acme = {
acceptTerms = true;
defaults.email = "nickforanick@protonmail.com";
};
}

38
boxes/netbox/radicale.nix Normal file
View File

@ -0,0 +1,38 @@
{ lib, config, pkgs, ... }:
{
services.radicale = {
enable = true;
settings = {
auth = {
type = "htpasswd";
htpasswd_filename = "radicale-passwd";
htpasswd_encryption = "plain";
};
};
};
services.nginx.virtualHosts."radicale.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5232";
extraConfig = ''
proxy_set_header X-Script-Name /;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Authorization;
'';
};
};
services.nginx.virtualHosts."calendar.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
services.nginx.virtualHosts."cal.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "radicale.beepboop.systems";
};
}

View File

@ -0,0 +1,21 @@
{ lib, config, pkgs, ... }:
{
services.rss2email = {
enable = true;
to = "ryan@beepboop.systems";
feeds = {
"eff" = {
url = "https://www.eff.org/rss/updates.xml";
};
"nixos" = {
url = "https://nixos.org/blog/announcements-rss.xml";
};
"drewdevault" = {
url = "https://drewdevault.com/blog/index.xml";
};
"nullprogram" = {
url = "https://nullprogram.com/feed/";
};
};
};
}

13
boxes/netbox/ssh.nix Normal file
View File

@ -0,0 +1,13 @@
{ lib, config, pkgs, ... }:
{
services.openssh = {
enable = true;
ports = [55555];
settings = {
X11Forwarding = false;
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
}

19
boxes/netbox/sslh.nix Normal file
View File

@ -0,0 +1,19 @@
{ lib, config, pkgs, ... }:
{
services.sslh = {
enable = true;
settings.protocols = [
{
host = "localhost";
name = "ssh";
port = "55555";
service = "ssh";
}
{
host = "localhost";
name = "tls";
port = "442";
}
];
};
}

View File

@ -0,0 +1,22 @@
{ lib, config, pkgs, ... }:
{
services.vaultwarden.enable = true;
services.vaultwarden.config = {
DOMAIN = "https://bitwarden.beepboop.systems";
SIGNUPS_ALLOWED = false;
};
services.nginx.virtualHosts."bit.beepboop.systems" = {
forceSSL = true;
enableACME = true;
globalRedirect = "bitwarden.beepboop.systems";
};
services.nginx.virtualHosts."bitwarden.beepboop.systems" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8000";
};
};
}

View File

@ -1,19 +0,0 @@
{ lib, pkgs, config, ... }:
let
cfg = config.services.gmail_mail_bridge;
appEnv = pkgs.python3.withPackages (p: with p; [ waitress (callPackage ./gmail_mail_bridge/default.nix {}) ]);
in {
options.services.gmail_mail_bridge = {
enable = lib.mkEnableOption "Enable the gmail_mail_bridge";
};
config = lib.mkIf cfg.enable {
systemd.services.gmail_mail_bridge = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${appEnv}/bin/waitress-serve --port=8041 gmail_mail_bridge:app";
StandardOutput = "journal";
};
};
};
}

View File

@ -1 +0,0 @@
__pycache_/

View File

@ -1,10 +0,0 @@
synchronize email from gmail accounts whose OAuth access is heavily restricted
background
----------
my school district disabled external OAuth access to email, which is not cool. this script gets around this and creates a bridge so you can recieve emails from your school email.
do note that this is heavily unpolished and most definately insecure. there are some hardcoded credentials (which you can change, it just takes a little technical know-how)
have fun!

View File

@ -1,20 +0,0 @@
{ pkgs, pythonPackages ? (import <nixpkgs> {}).python3Packages }:
pythonPackages.buildPythonPackage {
name = "gmail_mail_bridge";
src = ./gmail_mail_bridge;
propagatedBuildInputs = [ pythonPackages.flask pkgs.system-sendmail ];
installPhase = ''
runHook preInstall
mkdir -p $out/${pythonPackages.python.sitePackages}
cp -r . $out/${pythonPackages.python.sitePackages}/gmail_mail_bridge
runHook postInstall
'';
shellHook = "export FLASK_APP=gmail_mail_bridge";
format = "other";
}

View File

@ -1,37 +0,0 @@
from flask import Flask
from flask import request
from flask import redirect
from flask import abort
import logging
import smtplib
import email
from subprocess import Popen, PIPE, STDOUT
pre_shared_secret = "amongus sussy imposter"
to = "ryan@beepboop.systems"
app = Flask(__name__)
def handle_post(request):
msg = email.message_from_string(request.form["payload"])
del msg["To"]
msg["To"] = to
if not msg["From"]:
msg["From"] = "unknown-sender@mail.beepboop.systems"
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
@app.route("/bridge-submit", methods = ["GET", "POST"])
def testing():
if request.method == 'POST':
data = request.form
if data['auth'] == pre_shared_secret:
handle_post(request)
else:
return 'you didn\'t use post'
return "default answer"

View File

@ -1,12 +0,0 @@
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-23.11") {} }:
pkgs.mkShell {
packages = [
(pkgs.python3.withPackages (ps: [
ps.flask
]))
pkgs.curl
pkgs.jq
];
}

View File

@ -1,23 +0,0 @@
// google-side synchronization
// add a minute-wise trigger for mail synchronization
// go to the sidebar, select triggers, add a new one, configure it
// to run syncMail every minute
function syncMail() {
var threads = GmailApp.search("label:need_processing");
var label = GmailApp.getUserLabelByName("need_processing");
for (var thread of threads) {
for (var message of GmailApp.getMessagesForThread(thread)) {
var formData = {
auth: 'amongus sussy imposter',
payload: message.getRawContent(),
};
var options = {
'method' : 'POST',
'payload' : formData
};
var resp = UrlFetchApp.fetch('https://mail.beepboop.systems/bridge-submit', options);
}
thread.removeLabel(label);
}
}

View File

@ -4,6 +4,8 @@
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
neovim neovim
(pkgs.callPackage ../builds/rebuild.nix {})
]; ];
nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.experimental-features = [ "nix-command" "flakes" ];

View File

@ -6,7 +6,6 @@
]; ];
environment.systemPackages = [ environment.systemPackages = [
(pkgs.callPackage ../builds/rebuild.nix {})
(pkgs.callPackage ../builds/st.nix { lightMode = false; }) (pkgs.callPackage ../builds/st.nix { lightMode = false; })
(pkgs.callPackage ../builds/utils.nix {}) (pkgs.callPackage ../builds/utils.nix {})
(pkgs.callPackage ../builds/statusbar {}) (pkgs.callPackage ../builds/statusbar {})