From 550bb19d01ecbd236cd93a20c0712087c7f2a64c Mon Sep 17 00:00:00 2001 From: albert Date: Fri, 12 Jul 2024 14:40:25 +0900 Subject: [PATCH] Add warsaw-ovh-01 configs --- .sops.yaml | 4 +- flake.nix | 25 +++- nixos/hosts/warsaw-ovh-01/containers.nix | 30 ++++ nixos/hosts/warsaw-ovh-01/cron.nix | 77 ++++++++++ nixos/hosts/warsaw-ovh-01/default.nix | 60 ++++++++ nixos/hosts/warsaw-ovh-01/disks.nix | 141 ++++++++++++++++++ nixos/hosts/warsaw-ovh-01/firewall.nix | 30 ++++ nixos/hosts/warsaw-ovh-01/wireguard.nix | 49 ++++++ .../{ovh-server.yaml => warsaw-ovh-01.yaml} | 0 9 files changed, 412 insertions(+), 4 deletions(-) create mode 100644 nixos/hosts/warsaw-ovh-01/containers.nix create mode 100644 nixos/hosts/warsaw-ovh-01/cron.nix create mode 100644 nixos/hosts/warsaw-ovh-01/default.nix create mode 100644 nixos/hosts/warsaw-ovh-01/disks.nix create mode 100644 nixos/hosts/warsaw-ovh-01/firewall.nix create mode 100644 nixos/hosts/warsaw-ovh-01/wireguard.nix rename secrets/hosts/{ovh-server.yaml => warsaw-ovh-01.yaml} (100%) diff --git a/.sops.yaml b/.sops.yaml index e5cb2d58..08969c49 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -14,7 +14,7 @@ keys: - &quitman-rpi4 - &nixos-desktop - &nuc-server - - &ovh_server + - &warsaw-ovh-01 creation_rules: @@ -90,7 +90,7 @@ creation_rules: - *osaka-linode-01 # Hosts - - path_regex: secrets\/hosts\/ovh-server\.yaml$ + - path_regex: secrets\/hosts\/warsaw-ovh-01\.yaml$ key_groups: - pgp: - *albert diff --git a/flake.nix b/flake.nix index a9118dad..107c128d 100644 --- a/flake.nix +++ b/flake.nix @@ -53,43 +53,64 @@ libx = import ./lib { inherit self inputs outputs stateVersion hmStateVersion; }; in { nixosConfigurations = { + # Linode VM's osaka-linode-01 = libx.mkHost { hostname = "osaka-linode-01"; type = "small";}; milan-linode-01 = libx.mkHost { hostname = "milan-linode-01"; type = "small";}; frankfurt-linode-01 = libx.mkHost { hostname = "frankfurt-linode-01"; type = "small";}; + + # Servers framework-server = libx.mkHost { hostname = "framework-server"; }; + warsaw-ovh-01 = libx.mkHost { hostname = "warsaw-ovh-01"; }; nuc-server = libx.mkHost { hostname = "nuc-server"; }; + + # User Machines nixos-desktop = libx.mkHost { hostname = "nixos-desktop"; unfree = true; desktop = "plasma6"; }; nixos-framework = libx.mkHost { hostname = "nixos-framework"; unfree = true; desktop = "plasma6"; }; + steamdeck = libx.mkDeck { hostname = "steamdeck"; desktop = "plasma6"; theme = "stylix"; }; + + # Raspberry Pi's backups-rpi4 = libx.mkHost { hostname = "backups-rpi4"; system = "aarch64-linux"; type = "small"; }; piaware-rpi4 = libx.mkHost { hostname = "piaware-rpi4"; system = "aarch64-linux"; type = "small"; }; quitman-rpi4 = libx.mkHost { hostname = "quitman-rpi4"; system = "aarch64-linux"; type = "small"; }; bakersfield-rpi4 = libx.mkHost { hostname = "bakersfield-rpi4"; system = "aarch64-linux"; type = "small"; }; - steamdeck = libx.mkDeck { hostname = "steamdeck"; desktop = "plasma6"; theme = "stylix"; }; }; homeConfigurations = { + # Linode VM's "albert@osaka-linode-01" = libx.mkHome { hostname = "osaka-linode-01"; type = "small"; }; "albert@milan-linode-01" = libx.mkHome { hostname = "milan-linode-01"; type = "small"; }; "albert@frankfurt-linode-01" = libx.mkHome { hostname = "frankfurt-linode-01"; type = "small"; }; + + # Servers "albert@framework-server" = libx.mkHome { hostname = "framework-server"; }; + "albert@waraw-ovh-01" = libx.mkHome { hostname = "waraw-ovh-01"; }; "albert@nuc-server" = libx.mkHome { hostname = "nuc-server"; }; + + # User Machines "albert@nixos-desktop" = libx.mkHome { hostname = "nixos-desktop"; desktop = "plasma6"; }; "albert@nixos-framework" = libx.mkHome { hostname = "nixos-framework"; desktop = "plasma6"; }; + "albert@steamdeck" = libx.mkHome { hostname = "steamdeck"; desktop = "plasma6"; }; + + # Raspberry Pi's "albert@backups-rpi4" = libx.mkHome { hostname = "backups-rpi4"; system = "aarch64-linux"; type = "small"; }; "albert@piaware-rpi4" = libx.mkHome { hostname = "piaware-rpi4"; system = "aarch64-linux"; type = "small"; }; "albert@quitman-rpi4" = libx.mkHome { hostname = "quitman-rpi4"; system = "aarch64-linux"; type = "small"; }; "albert@bakersfield-rpi4" = libx.mkHome { hostname = "bakersfield-rpi4"; system = "aarch64-linux"; type = "small"; }; - "albert@steamdeck" = libx.mkHome { hostname = "steamdeck"; desktop = "plasma6"; }; + # Containers "albert@rdesktop" = libx.mkHome { hostname = "rdesktop"; desktop = "plasma6"; }; }; deploy.nodes = { + # Linode VM's osaka-linode-01 = libx.deploy { hostname = "osaka-linode-01"; }; milan-linode-01 = libx.deploy { hostname = "milan-linode-01"; }; frankfurt-linode-01 = libx.deploy { hostname = "frankfurt-linode-01"; }; + # Servers framework-server = libx.deploy { hostname = "framework-server"; }; + ovh-server = libx.deploy { hostname = "ovh-server"; }; # nuc-server = libx.deploy { hostname = "nuc-server"; }; + # Raspberry Pi's backups-rpi4 = libx.deploy { hostname = "backups-rpi4"; system = "aarch64-linux"; }; piaware-rpi4 = libx.deploy { hostname = "piaware-rpi4"; system = "aarch64-linux"; }; bakersfield-rpi4 = libx.deploy { hostname = "bakersfield-rpi4"; system = "aarch64-linux"; }; diff --git a/nixos/hosts/warsaw-ovh-01/containers.nix b/nixos/hosts/warsaw-ovh-01/containers.nix new file mode 100644 index 00000000..e2605825 --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/containers.nix @@ -0,0 +1,30 @@ +{ lib, self, inputs, outputs, stateVersion, hmStateVersion, ... }: +let + libx = import ../../../lib { inherit lib self inputs outputs stateVersion hmStateVersion; }; +in { + + containers = { + rdesktop = libx.mkContainer { hostname = "rdesktop"; ip = "2"; desktop = "plasma6"; unfree = true; }; + }; + + # Networking config + networking.bridges.nix-br0.interfaces = []; + + # Add an IP address to the bridge interface. + networking.localCommands = ''ip address add 192.168.2.1/24 dev nix-br0''; + + # Firewall commands allowing traffic to go in and out of the bridge interface + # (and to the guest LXD instance). Also sets up the actual NAT masquerade rule. + networking.firewall.extraCommands = '' + iptables -A INPUT -i nix-br0 -j ACCEPT + + # These three technically aren't needed, since by default the FORWARD and + # OUTPUT firewalls accept everything everything, but lets keep them in just + # in case. + iptables -A FORWARD -o nix-br0 -j ACCEPT + iptables -A FORWARD -i nix-br0 -j ACCEPT + iptables -A OUTPUT -o nix-br0 -j ACCEPT + + iptables -t nat -A POSTROUTING -s 192.168.2.0/24 ! -d 192.168.2.0/24 -j MASQUERADE + ''; +} diff --git a/nixos/hosts/warsaw-ovh-01/cron.nix b/nixos/hosts/warsaw-ovh-01/cron.nix new file mode 100644 index 00000000..97b4e90f --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/cron.nix @@ -0,0 +1,77 @@ +{ pkgs, ... }: { + services.cron = { + enable = true; + systemCronJobs = [ + # Backups to nuc-docker01 + ''0 0 * * * root rsync --delete -avr /Storage/Data/Docker/sysctl.io/ root@nuc-docker01:/Storage/Data/Docker/sysctl.io/'' + ''0 3 * * * root rsync -avr /Storage/Data/Docker/sysctl.io/nextcloud/html/data/albert/files/InstantUpload/ root@nuc-docker01:/Storage/Media/Pictures/InstantUpload/'' + ''0 5 * * * root rsync -avr /Storage/Data/Docker/sysctl.io/nextcloud/html/data/albert/files/Wallpapers/ root@nuc-docker01:/Storage/Media/Pictures/Wallpapers'' + # Back up the docker containers monthly: + ''@monthly root ssh nuc-docker01 "rm -rf /Storage/Backups/Docker/sysctl.io/*"; for i in $(docker ps --format '{{.Names}}'); do docker export $i | gzip -cf | ssh root@nuc-docker01 "cat > /Storage/Backups/Docker/sysctl.io/$i.tar.gz"; done'' + # Set a random Pi-Hole password + ''* * * * * root docker exec pihole sudo pihole -a -p $(openssl rand -hex 128)'' + # Run the ClamAV scan + ''@monthly root /Storage/Data/docker-compose/sysctl.io/scripts/clamscan-cron.sh'' + # Archive Loki logs monthly + ''@monthly root /Storage/Data/docker-compose/sysctl.io/scripts/backup-logs.sh >> /Storage/Data/Temporary/log_backups.log'' + # Run the Nextcloud cronjobs hourly + ''@hourly root docker exec -uwww-data nextcloud php -f /var/www/html/cron.php'' + # Run the Pixelfed scheduler + ''* * * * * root docker exec pixelfed-app php artisan schedule:run'' + # Update / CLean Mastodon caches + ''@daily root docker exec mastodon-web tootctl preview_cards remove --days 7'' + ''@daily root docker exec mastodon-web tootctl media remove --days 7 --prune-profiles'' + ''@daily root docker exec mastodon-web tootctl accounts prune'' + ''@daily root docker exec mastodon-web tootctl statuses remove --days 7'' + ''@daily root docker exec mastodon-web tootctl media remove --remove-headers --include-follows --days 7'' + ''@daily root docker exec mastodon-web tootctl preview_cards remove --days 7'' + ''@daily root docker exec mastodon-web tootctl media remove-orphans'' + ]; + }; +} +# Old crontab: +# # At reboot, apply the ip_tables modprobe so Wireguard works +# @reboot /usr/sbin/modprobe ip_tables +# +# # At reboot, restart Docker. Otherwise, iptables / the firewall freaks out +# @reboot /usr/bin/systemctl stop docker; /usr/bin/systemctl start docker +# +# # Every day, get storage space for monitoring +# @daily source ~/.bashrc; for i in `ls /Storage/Data/Docker`; do echo echo "$(date): $(du -s /Storage/Data/Docker/$i)" | sed -e 's/\/Storage\/Data\/Docker\/\$i//' >> /root/sizes/$i.log; done +# +# # Clean up NextCloud files weekly to save space +# @weekly source ~/.bashrc; /usr/bin/docker exec -uwww-data nextcloud php occ versions:cleanup +# DONE # Run the Nextcloud cronjobs hourly +# DONE @hourly source ~/.bashrc; /usr/bin/docker exec -uwww-data nextcloud php -f /var/www/html/cron.php +# +# +# # Clear out Mastodon caches daily +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl preview_cards remove --days 1 +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl media remove --days 1 --prune-profiles +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl accounts prune +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl statuses remove --days 1 +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl media remove --remove-headers --include-follows --days 0 +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl preview_cards remove --days 1 +# DONE @daily source ~/.bashrc; /usr/bin/docker exec mastodon-web tootctl media remove-orphans +# +# DONE # Run the Pixelfed scheduler +# DONE * * * * * /usr/bin/docker exec pixelfed-app php artisan schedule:run +# +# DONE # Run the ClamAV scan +# DONE @monthly source ~/.bashrc; /Storage/Data/docker-compose/sysctl.io/scripts/clamscan-cron.sh +# +# DONE # Set a random PiHole password every minute +# DONE * * * * * /usr/bin/docker exec pihole sudo pihole -a -p $(openssl rand -hex 128) +# +# NOT NEEDED # back up crontab: +# NOT NEEDED # 0 0 * * * /usr/bin/crontab -l > /Storage/Data/Temporary/crontab +# +# # Back up and delete local copies of Loki logs monthly +# DONE @monthly source ~/.bashrc; /Storage/Data/docker-compose/sysctl.io/scripts/backup-logs.sh >> /Storage/Data/Temporary/log_backups.log +# +# DONE # Back up the docker containers weekly: +# DONE @weekly source ~/.bashrc; ssh nuc-docker01 "rm -rf /Storage/Backups/Docker/sysctl.io/*"; for i in $(docker ps --format '{{.Names}}'); do docker export $i | gzip -cf | ssh root@nuc-docker01 "cat > /Storage/Backups/Docker/sysctl.io/$i.tar.gz"; done +# +# # Set up DERP relay certs for headscale-derp: +# DONE @hourly cp /Storage/Data/Docker/letsencrypt/certs/certs/\*.sysctl.io.crt /Storage/Data/Docker/letsencrypt/certs/certs/derp.sysctl.io.crt +# DONE @hourly cp /Storage/Data/Docker/letsencrypt/certs/private/\*.sysctl.io.key /Storage/Data/Docker/letsencrypt/certs/private/derp.sysctl.io.key diff --git a/nixos/hosts/warsaw-ovh-01/default.nix b/nixos/hosts/warsaw-ovh-01/default.nix new file mode 100644 index 00000000..727f7392 --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/default.nix @@ -0,0 +1,60 @@ +{ inputs, config, lib, pkgs, hostname, modulesPath, system, ... }: { + imports = [ + inputs.nixos-hardware.nixosModules.framework-13th-gen-intel + (modulesPath + "/installer/scan/not-detected.nix") + ../../common/modules/secureboot.nix + ../../common/modules/udev-rules.nix + ../../common/modules/builder.nix + ../../common/services/fwupd.nix + ../../common/modules/ssh-luks.nix + ../../common/services/docker.nix + ../../common/services/tailscale-autoconnect.nix + ./containers.nix + ./disks.nix + ./wireguard.nix + ./cron.nix + ./firewall.nix + ]; + + environment.systemPackages = [ + inputs.deploy-rs.packages.${system}.deploy-rs + pkgs.distrobox + ]; + + # backups-rpi4 cron job to back up sysctl.io's Docker files + # osaka-linode-01 cron job to copy certs for the DERP relay + # milan-linode-01 cron job to copy certs for the DERP relay + # frankfurt-linode-01 cron job to copy certs for the DERP relay + users.users.root.openssh.authorizedKeys.keys = [ + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKp2wgqFcr0LGaUXbom88/zK2631pysePUWIaCMljT0K root@backups-rpi4'' + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKkNFdEcYIrjss1Nz0tU/AX89hUMmxB/Vabvsa7A6E2K root@osaka-linode-01'' + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIORCrD/ZWXbAfi5eIN8b9dwuvMuPPTgpMiIFh1WagXV2 root@milan-linode-01'' + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBGXiWUR2T5HXQ4g/En+eJ9K6GSokl3tEK7RZcYb+0UA root@frankfurt-linode-01'' + ]; + services.openssh.settings.PermitRootLogin = lib.mkForce "prohibit-password"; + + boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "thunderbolt" "sd_mod" "uas" ]; + boot.initrd.kernelModules = [ "r8152" ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = with config.boot.kernelPackages; [ acpi_call ]; + + networking.useDHCP = lib.mkDefault true; + powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + # Set your time zone. + time.timeZone = "Europe/Warsaw"; + + # Set the networking hostname: + networking.hostName = hostname; + networking.firewall.allowedTCPPorts = [ 22 ]; + + services.tailscale.extraUpFlags = [ + "--advertise-exit-node" + "--advertise-routes=10.2.0.0/24" + ]; + + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = true; + }; +} diff --git a/nixos/hosts/warsaw-ovh-01/disks.nix b/nixos/hosts/warsaw-ovh-01/disks.nix new file mode 100644 index 00000000..a963a5ab --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/disks.nix @@ -0,0 +1,141 @@ +{ + # Disks are sdb and sdc + # https://github.com/nix-community/disko/blob/master/example/boot-raid1.nix + imports = [ ../../common/services/snapper.nix ]; + + # extra configs not present in the standard config above + services.snapper.configs.Storage = { + TIMELINE_CREATE = true; + TIMELINE_CLEANUP = true; + SUBVOLUME = "/Storage"; + }; + + services.btrfs.autoScrub.enable = true; + services.btrfs.autoScrub.interval = "weekly"; + + disko.devices.disk = { + sdb = { + type = "disk"; + device = "/dev/sdb"; + content = { + type = "gpt"; + partitions = { + BOOT = { + size = "1M"; + type = "EF02"; # GRUB MBR + }; + ESP = { + size = "500M"; + type = "EF00"; + content = { + type = "mdraid"; + name = "boot"; + }; + }; + mdadm = { + size = "100%"; + content = "mdraid"; + name = "raid1"; + }; + }; + }; + }; + + sdc = { + type = "disk"; + device = "/dev/sdc"; + content = { + type = "gpt"; + partitions = { + BOOT = { + size = "1M"; + type = "EF02"; # GRUB MBR + }; + ESP = { + size = "500M"; + type = "EF00"; + content = { + type = "mdraid"; + name = "boot"; + }; + }; + mdadm = { + size = "100%"; + content = "mdraid"; + name = "raid1"; + }; + }; + }; + }; + + mdadm = { + boot = { + type = "mdadm"; + level = 1; + metadata = "1.0"; + content = { + type = "Filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + raid1 = { + type = "mdadm"; + level = 1; + content = { + type = "gpt"; + partitions = { + LUKS-ROOT = { + start = "550MiB"; + end = "100%"; + content = { + type = "luks"; + name = "ROOT"; + extraOpenArgs = [ "--allow-discards" ]; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # root + "/home" = { + mountpoint = "/home"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # home + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # nix + "/Storage" = { + mountpoint = "/Storage"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # Storage + # SNAPSHOT SUBVOLS + "/root/.snapshots" = { + mountpoint = "/.snapshots"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # root + "/home/.snapshots" = { + mountpoint = "/home/.snapshots"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # home + "/nix/.snapshots" = { + mountpoint = "/nix/.snapshots"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # nix + "/Storage/.snapshots" = { + mountpoint = "/Storage/.snapshots"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; # Storage + }; # subvolumes + }; # content.content + }; # content + }; # partition 2 (/ BTRFS) + }; + }; + }; + }; + }; diff --git a/nixos/hosts/warsaw-ovh-01/firewall.nix b/nixos/hosts/warsaw-ovh-01/firewall.nix new file mode 100644 index 00000000..4397eedc --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/firewall.nix @@ -0,0 +1,30 @@ +{ ... }: { + networking = { + firewall = { + enable = true; + allowedTCPPorts = [ + 53 # DNS + 80 # HTTP + 443 # HTTPS + 42420 # Vintage Story + 25565 # Minecraft + 1443 # Headscale DERP (tcp) + 25 # Mailserver + 143 # Mailserver + 465 # Mailserver + 587 # Mailserver + 993 # Mailserver + 4190 # Mailserver + 5696 # dsm-kmip server + 3389 # RDP + 4443 # Jitsi + ]; + allowedUDPPorts = [ + 53 # DNS (udp) + 10000 # Jitsi Meet (udp) + 15636 # Enshrouded - Game + 15637 # Enshrouded - Query Port + ]; + }; + }; +} diff --git a/nixos/hosts/warsaw-ovh-01/wireguard.nix b/nixos/hosts/warsaw-ovh-01/wireguard.nix new file mode 100644 index 00000000..5508c05c --- /dev/null +++ b/nixos/hosts/warsaw-ovh-01/wireguard.nix @@ -0,0 +1,49 @@ +{ ... }: { + + # Allow these hosts to directly communicate with their hostnames + networking.extraHosts = '' + 10.100.0.1 osaka-linode-01 + 10.100.0.2 framework-servr + ''; + + networking.firewall.interfaces.wireguard0.allowedTCPPorts = [ 22 ]; + + # Set up the secrets file: + sops.secrets."wireguard_key" = { + owner = "root"; + sopsFile = ../../../secrets/hosts/warsaw-ovh-01.yaml; + }; + sops.secrets."preshared_key" = { + owner = "root"; + sopsFile = ../../../secrets/wireguard.yaml; + }; + + # Wireguard Forwarder + networking.wireguard = { + enable = true; + interfaces = { + "wireguard0" = { + ips = [ "10.100.0.2/24" ]; + listenPort = 51820; + privateKeyFile = "/run/secrets/wireguard_key"; + # Testing + peers = [ + { # osaka-linode-01 + publicKey = "yPZ3EmmIqCkReXf1DRTxzVaKQ2k+ifGmYJHji5nnMmE="; + presharedKeyFile = "/run/secrets/preshared_key"; + persistentKeepalive = 5; + allowedIPs = [ "10.100.0.1/32" ]; + endpoint = "172.234.84.222:51820"; # osaka-linode-01 + } + { # frankfurt-linode-01 + publicKey = "9FCIy07RvR2dz8bbPUB9h2jdhFQHfDh0VdLf06n46QQ="; + presharedKeyFile = "/run/secrets/preshared_key"; + persistentKeepalive = 5; + allowedIPs = [ "10.100.0.4/32" ]; + endpoint = "172.105.76.221:51820"; # frankfurt-linode-01 + } + ]; + }; + }; + }; +} diff --git a/secrets/hosts/ovh-server.yaml b/secrets/hosts/warsaw-ovh-01.yaml similarity index 100% rename from secrets/hosts/ovh-server.yaml rename to secrets/hosts/warsaw-ovh-01.yaml