diff --git a/hosts/hetzner-vm/hardware.nix b/hosts/hetzner-vm/hardware.nix new file mode 100644 index 0000000..9df81e2 --- /dev/null +++ b/hosts/hetzner-vm/hardware.nix @@ -0,0 +1,13 @@ +{ modulesPath, ... }: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; + boot.initrd.kernelModules = [ "nvme" ]; + fileSystems."/" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; +} diff --git a/hosts/hetzner-vm/hetzner-vm.nix b/hosts/hetzner-vm/hetzner-vm.nix index 46e9843..551c317 100644 --- a/hosts/hetzner-vm/hetzner-vm.nix +++ b/hosts/hetzner-vm/hetzner-vm.nix @@ -3,15 +3,14 @@ { imports = with tree; [ users.root - users.chaos profiles.base profiles.tailscale profiles.sshd profiles.nginx + profiles.nix-gc hosts.hetzner-vm.services.restic - hosts.hetzner-vm.services.nginx hosts.hetzner-vm.services.invidious hosts.hetzner-vm.services.quassel hosts.hetzner-vm.services.mpd @@ -21,7 +20,8 @@ hosts.hetzner-vm.services.lappy-dev hosts.hetzner-vm.services.misskey - (modulesPath + "/profiles/qemu-guest.nix") + ./networking.nix + ./hardware.nix ]; networking.firewall.allowedTCPPorts = [ 80 443 ]; @@ -30,47 +30,10 @@ imports = with tree; [ home.base home.dev.small ]; home.stateVersion = "22.05"; }; - home-manager.users.chaos = { - imports = with tree; [ home.base home.dev.small ]; - home.stateVersion = "22.05"; - }; - - nix.settings.auto-optimise-store = true; - nix.gc = { - automatic = true; - dates = "daily"; - options = "--delete-older-than 1d"; - }; networking.hostName = "hetzner-vm"; time.timeZone = "Europe/London"; - systemd.services.systemd-networkd-wait-online.enable = false; - - networking.firewall.enable = true; - networking.firewall.allowPing = true; - networking.firewall.allowedTCPPorts = [ 22 ]; - - networking.enableIPv6 = true; - networking.usePredictableInterfaceNames = false; - networking.dhcpcd.enable = true; - systemd.network = { - enable = true; - networks.eth0 = { - name = "eth0"; - address = [ "2a01:4f9:c010:8beb::1/64" ]; - gateway = [ "fe80::1" ]; - }; - }; - - boot.loader.grub.enable = true; - boot.loader.grub.device = "/dev/sda"; - boot.initrd.kernelModules = [ "nvme" ]; - fileSystems."/" = { - device = "/dev/sda1"; - fsType = "ext4"; - }; - system.stateVersion = "21.11"; } diff --git a/hosts/hetzner-vm/networking.nix b/hosts/hetzner-vm/networking.nix new file mode 100644 index 0000000..415db58 --- /dev/null +++ b/hosts/hetzner-vm/networking.nix @@ -0,0 +1,19 @@ +{ ... }: { + systemd.services.systemd-networkd-wait-online.enable = false; + + networking.firewall.enable = true; + networking.firewall.allowPing = true; + networking.firewall.allowedTCPPorts = [ 22 ]; + + networking.enableIPv6 = true; + networking.usePredictableInterfaceNames = false; + networking.dhcpcd.enable = true; + systemd.network = { + enable = true; + networks.eth0 = { + name = "eth0"; + address = [ "2a01:4f9:c010:8beb::1/64" ]; + gateway = [ "fe80::1" ]; + }; + }; +} diff --git a/hosts/hetzner-vm/services/mpd.nix b/hosts/hetzner-vm/services/mpd.nix index abec458..e4e67e2 100644 --- a/hosts/hetzner-vm/services/mpd.nix +++ b/hosts/hetzner-vm/services/mpd.nix @@ -19,7 +19,7 @@ metadata_to_use "title,artist" auto_update "yes" audio_buffer_size "4096" - #replaygain "track" + replaygain "track" audio_output_format "44100:16:2" audio_output { type "httpd" @@ -39,8 +39,6 @@ encoder "flac" port "8013" format "44100:16:2" - #oggflac "yes" - #oggchaining "yes" always_on "yes" tags "yes" } diff --git a/hosts/hetzner-vm/services/restic.nix b/hosts/hetzner-vm/services/restic.nix index c3e8b97..cabbe45 100644 --- a/hosts/hetzner-vm/services/restic.nix +++ b/hosts/hetzner-vm/services/restic.nix @@ -3,87 +3,59 @@ let mail_config = (import ./mailserver/config.nix { }); - backupUser = "root"; - backupPaths = [ - "/secrets" - - "/var/lib/vault" - "/var/lib/acme" - # Quassel & Invidious - "/var/backup/postgresql" - "/home/quassel/.config/quassel-irc.org" - # MPD State - "/mpd" - # doesn't work for restoring might as well not backup - # "/var/lib/tailscale" - - # mail - mail_config.vmail_config.directory - mail_config.sieve_directory - mail_config.dkim_directory - "/var/lib/redis-rspamd" - - # misskey - "/home/misskey/misskey-files" - "/var/lib/redis-misskey" - - ]; backupPrepareCommand = "${ (pkgs.writeShellScriptBin "backupPrepareCommand" '' systemctl start postgresqlBackup --wait '') }/bin/backupPrepareCommand"; - - timerConfig = { - OnBootSec = "1m"; - OnCalendar = "daily"; - }; - repos = { - Chaos-Backups-HetznerVM = { - # repository is overrided in environmentFile to contain auth - # make sure to keep up to date when changing repository - repository = "rest:https://storage-restic.owo.monster/HetznerVM"; - passwordFile = "/secrets/restic-Chaos-Backups-HetznerVM-password"; - environmentFile = "/secrets/restic-Chaos-Backups-HetznerVM-env"; - }; - Cassie-Backups-HetznerVM = { - repository = "b2:Cryptidz-Backup:HetznerVM"; - passwordFile = "/secrets/restic-Cassie-Backups-HetznerVM-password"; - environmentFile = "/secrets/restic-Cassie-Backups-HetznerVM-env"; - }; - }; - - restic_commands = lib.mapAttrsToList (repoName: repoInfo: - ( - # nya - pkgs.writeShellScriptBin "restic-${repoName}" '' - env \ - RESTIC_PASSWORD_FILE=${repoInfo.passwordFile} \ - RESTIC_REPOSITORY=${repoInfo.repository} \ - $(cat ${repoInfo.environmentFile}) \ - ${pkgs.restic}/bin/restic $@ - '')) repos; in { - environment.systemPackages = restic_commands; + environment.systemPackages = [ + (pkgs.writeShellScriptBin "restic-hetzner-vm" '' + env \ + RESTIC_PASSWORD_FILE=/secrets/restic-Chaos-Backups-HetznerVM-password \ + $(cat /secrets/restic-Chaos-Backups-HetznerVM-env) \ + ${pkgs.restic}/bin/restic $@ + '') + ]; - services.restic.backups.hetzner-vm = lib.mkMerge [ - { - user = backupUser; - paths = backupPaths; - inherit timerConfig; - inherit backupPrepareCommand; - } - repos.Chaos-Backups-HetznerVM - ]; - services.restic.backups.cassie-hetzner-vm = lib.mkMerge [ - { - user = backupUser; - paths = backupPaths; - inherit timerConfig; - inherit backupPrepareCommand; - } - repos.Cassie-Backups-HetznerVM - ]; + services.restic.backups.hetzner-vm = { + user = "root"; + paths = [ + "/secrets" + + "/var/lib/acme" + # Quassel & Invidious + "/var/backup/postgresql" + "/home/quassel/.config/quassel-irc.org" + # MPD State + "/mpd" + # doesn't work for restoring might as well not backup + # "/var/lib/tailscale" + + # mail + mail_config.vmail_config.directory + mail_config.sieve_directory + mail_config.dkim_directory + "/var/lib/redis-rspamd" + + # misskey + "/home/misskey/misskey-files" + "/var/lib/redis-misskey" + ]; + + # repository is overrided in environmentFile to contain auth + # make sure to keep up to date when changing repository + repository = "rest:https://storage-restic.owo.monster/HetznerVM"; + passwordFile = "/secrets/restic-Chaos-Backups-HetznerVM-password"; + environmentFile = "/secrets/restic-Chaos-Backups-HetznerVM-env"; + + timerConfig = { + OnBootSec = "1m"; + OnCalendar = "daily"; + }; + + inherit backupPrepareCommand; + }; services.postgresqlBackup = { enable = true; diff --git a/hosts/storage/hardware.nix b/hosts/storage/hardware.nix index 8ee92b3..9df81e2 100644 --- a/hosts/storage/hardware.nix +++ b/hosts/storage/hardware.nix @@ -1,7 +1,6 @@ { modulesPath, ... }: { imports = [ (modulesPath + "/profiles/qemu-guest.nix") - ]; boot.loader.grub.enable = true; diff --git a/hosts/storage/populate-rclone-config.sh b/hosts/storage/populate-rclone-config.sh index 74d3e60..73b0a11 100755 --- a/hosts/storage/populate-rclone-config.sh +++ b/hosts/storage/populate-rclone-config.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -ex +set -ex -o pipefail kv_get() { vault kv get -format json ${1} @@ -39,6 +39,10 @@ B2_CHAOS_PHOTOS_KEY=$(simple_get /api-keys/backblaze/Chaos-Photos .applicationKe sed -i "s/B2_CHAOS_PHOTOS_ACCOUNT/${B2_CHAOS_PHOTOS_ACCOUNT}/" ./template sed -i "s/B2_CHAOS_PHOTOS_KEY/${B2_CHAOS_PHOTOS_KEY}/" ./template +B2_CASSIE_CRYPTIDZ_BACKUP_ACCOUNT=$(simple_get /api-keys/backblaze/Cryptidz-Backup .keyID) +B2_CASSIE_CRYPTIDZ_BACKUP_KEY=$(simple_get /api-keys/backblaze/Cryptidz-Backup .applicationKey | sed "s#/#\\\/#") +sed -i "s/B2_CASSIE_CRYPTIDZ_BACKUP_ACCOUNT/${B2_CASSIE_CRYPTIDZ_BACKUP_ACCOUNT}/" ./template +sed -i "s/B2_CASSIE_CRYPTIDZ_BACKUP_KEY/${B2_CASSIE_CRYPTIDZ_BACKUP_KEY}/" ./template popd cat "${TMP_DIR}/template" > "${OUTPUT_FILE}" diff --git a/hosts/storage/rclone_config.template b/hosts/storage/rclone_config.template index 167520f..0d7f3dc 100644 --- a/hosts/storage/rclone_config.template +++ b/hosts/storage/rclone_config.template @@ -26,4 +26,14 @@ hard_delete = true [B2-Chaos-Photos] type = alias -remote = B2-Chaos-Photos-Source:Chaos-Photos \ No newline at end of file +remote = B2-Chaos-Photos-Source:Chaos-Photos + +[B2-Cassie-Cryptidz-Backup-Source] +type = b2 +account = B2_CASSIE_CRYPTIDZ_BACKUP_ACCOUNT +key = B2_CASSIE_CRYPTIDZ_BACKUP_KEY +hard_delete = true + +[B2-Cassie-Cryptidz-Backup] +type = alias +remote = B2-Cassie-Cryptidz-Backup-Source:Cryptidz-Backup \ No newline at end of file diff --git a/hosts/storage/secrets-db.nix b/hosts/storage/secrets-db.nix new file mode 100644 index 0000000..b6b1b7f --- /dev/null +++ b/hosts/storage/secrets-db.nix @@ -0,0 +1,32 @@ +{ }: { + restic_hetznervm_htpasswd = { + user = "storage"; + group = "storage"; + permissions = "660"; + path = "/secrets/restic_hetznervm_htpasswd"; + }; + restic_music_htpasswd = { + user = "storage"; + group = "storage"; + permissions = "660"; + path = "/secrets/restic_music_htpasswd"; + }; + restic_vault_htpasswd = { + user = "storage"; + group = "storage"; + permissions = "660"; + path = "/secrets/restic_vault_htpasswd"; + }; + webdav_htpasswd = { + user = "storage"; + group = "storage"; + permissions = "660"; + path = "/secrets/webdav_htpasswd"; + }; + vault_password = { + user = "root"; + group = "root"; + permissions = "660"; + path = "/secrets/vault_password"; + }; +} diff --git a/hosts/storage/secrets.nix b/hosts/storage/secrets.nix new file mode 100644 index 0000000..1e72b3e --- /dev/null +++ b/hosts/storage/secrets.nix @@ -0,0 +1,63 @@ +{ pkgs, ... }: +let secrets-db = (import ./secrets-db.nix { }); +in { + systemd.tmpfiles.rules = [ "d /secrets - root root" ]; + environment.systemPackages = [ + (pkgs.writeShellScriptBin "init-secrets" '' + set -e -o pipefail + + VAULT_ADDR_DEFAULT="https://vault.owo.monster" + [ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" + + export PATH=$PATH:${pkgs.vault}/bin + export PATH=$PATH:${pkgs.jq}/bin + export PATH=$PATH:${pkgs.apacheHttpd}/bin + + kv_get() { + vault kv get -format json $1 + } + + simple_get() { + kv_get $1 | jq .data.data$2 -r + } + + file=${secrets-db.restic_hetznervm_htpasswd.path} + echo $file + username=$(simple_get "/api-keys/storage/restic/HetznerVM" .username) + password=$(simple_get "/api-keys/storage/restic/HetznerVM" .password) + htpasswd -bc $file "$username" "$password" + chown ${secrets-db.restic_hetznervm_htpasswd.user}:${secrets-db.restic_hetznervm_htpasswd.group} $file + chmod ${secrets-db.restic_hetznervm_htpasswd.permissions} $file + + file=${secrets-db.restic_music_htpasswd.path} + echo $file + username=$(simple_get "/api-keys/storage/restic/Music" .username) + password=$(simple_get "/api-keys/storage/restic/Music" .password) + htpasswd -bc $file "$username" "$password" + chown ${secrets-db.restic_music_htpasswd.user}:${secrets-db.restic_music_htpasswd.group} $file + chmod ${secrets-db.restic_music_htpasswd.permissions} $file + + file=${secrets-db.restic_vault_htpasswd.path} + echo $file + username=$(simple_get "/api-keys/storage/restic/Vault" .username) + password=$(simple_get "/api-keys/storage/restic/Vault" .password) + htpasswd -bc $file "$username" "$password" + chown ${secrets-db.restic_vault_htpasswd.user}:${secrets-db.restic_vault_htpasswd.group} $file + chmod ${secrets-db.restic_vault_htpasswd.permissions} $file + + file=${secrets-db.webdav_htpasswd.path} + echo $file + username=$(simple_get "/api-keys/storage/webdav" .username) + password=$(simple_get "/api-keys/storage/webdav" .password) + htpasswd -bc $file "$username" "$password" + chown ${secrets-db.webdav_htpasswd.user}:${secrets-db.webdav_htpasswd.group} $file + chmod ${secrets-db.webdav_htpasswd.permissions} $file + + file=${secrets-db.vault_password.path} + echo $file + simple_get "/vault-users/storage" .password > $file + chown ${secrets-db.vault_password.user}:${secrets-db.vault_password.group} $file + chmod ${secrets-db.vault_password.permissions} $file + '') + ]; +} diff --git a/hosts/storage/storage.nix b/hosts/storage/storage.nix index bb04f3f..341aaa2 100644 --- a/hosts/storage/storage.nix +++ b/hosts/storage/storage.nix @@ -1,6 +1,6 @@ { modulesPath, tree, config, pkgs, lib, ... }: - -{ +let secrets-db = (import ./secrets-db.nix { }); +in { imports = with tree; [ users.root @@ -11,15 +11,14 @@ ./hardware.nix ./networking.nix + ./secrets.nix ]; systemd.tmpfiles.rules = [ - "d /secrets - root root" - # + "d /storage - root root" ]; - users.groups.storage = { }; users.users.storage = { isNormalUser = true; @@ -32,17 +31,20 @@ path = with pkgs; [ bash rclone vault getent jq ]; script = let vault_username = "storage"; - vault_password_file = "/secrets/vault_password"; + vault_password_file = "${secrets-db.vault_password.path}"; + + config_dir = "/home/storage/.config/rclone"; + config_file = "/home/storage/.config/rclone/rclone.conf"; in '' - mkdir -p /home/storage/.config/rclone + mkdir -p ${config_dir} VAULT_ADDR="https://vault.owo.monster" bash ${ ./populate-rclone-config.sh } ${vault_username} ${vault_password_file} ${ ./rclone_config.template - } /home/storage/.config/rclone/rclone.conf - chown storage:storage /home/storage/.config/rclone/rclone.conf - chmod 660 /home/storage/.config/rclone/rclone.conf + } ${config_file} + chown storage:storage ${config_file} + chmod 660 ${config_file} ''; }; @@ -68,7 +70,8 @@ remote = "StorageBox:"; type = "webdav"; wants = [ "populate-rclone-config.service" ]; - extraArgs = [ "--addr=:4242" "--htpasswd=/secrets/webdav_htpasswd" ]; + extraArgs = + [ "--addr=:4242" "--htpasswd=${secrets-db.webdav_htpasswd.path}" ]; } { user = "storage"; @@ -77,7 +80,7 @@ wants = [ "populate-rclone-config.service" ]; extraArgs = [ "--addr=:4243" - "--htpasswd=/secrets/restic_hetznervm_htpasswd" + "--htpasswd=${secrets-db.restic_hetznervm_htpasswd.path}" "--baseurl=/HetznerVM/" ]; } @@ -88,7 +91,7 @@ wants = [ "populate-rclone-config.service" ]; extraArgs = [ "--addr=:4244" - "--htpasswd=/secrets/restic_music_htpasswd" + "--htpasswd=${secrets-db.restic_music_htpasswd.path}" "--baseurl=/Music/" ]; } @@ -99,7 +102,7 @@ wants = [ "populate-rclone-config.service" ]; extraArgs = [ "--addr=:4245" - "--htpasswd=/secrets/restic_vault_htpasswd" + "--htpasswd=${secrets-db.restic_vault_htpasswd.path}" "--baseurl=/Vault/" ]; } @@ -146,6 +149,25 @@ OnCalendar = "4h"; }; } + + { + source = "StorageBox:Chaos-Backups"; + dest = "B2-Cassie-Cryptidz-Backup:Chaos-Backups"; + wants = [ "populate-rclone-config.service" ]; + timerConfig = { + OnStartupSec = "60"; + OnCalendar = "4h"; + }; + } + { + source = "StorageBox:Chaos-Photos"; + dest = "B2-Cassie-Cryptidz-Backup:Chaos-Photos"; + wants = [ "populate-rclone-config.service" ]; + timerConfig = { + OnStartupSec = "60"; + OnCalendar = "4h"; + }; + } ]; }; diff --git a/hosts/vault/hardware.nix b/hosts/vault/hardware.nix index 8ee92b3..9df81e2 100644 --- a/hosts/vault/hardware.nix +++ b/hosts/vault/hardware.nix @@ -1,7 +1,6 @@ { modulesPath, ... }: { imports = [ (modulesPath + "/profiles/qemu-guest.nix") - ]; boot.loader.grub.enable = true; diff --git a/hosts/vault/secrets.nix b/hosts/vault/secrets.nix index 784f56c..2769363 100644 --- a/hosts/vault/secrets.nix +++ b/hosts/vault/secrets.nix @@ -1,10 +1,12 @@ { pkgs, ... }: let secrets-db = (import ./secrets-db.nix { }); in { + systemd.tmpfiles.rules = [ "d /secrets - root root" ]; environment.systemPackages = [ (pkgs.writeShellScriptBin "init-secrets" '' - VAULT_ADDR_DEFAULT="https://vault.owo.monster" + set -e -o pipefail + VAULT_ADDR_DEFAULT="https://vault.owo.monster" [ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" export PATH=$PATH:${pkgs.vault}/bin diff --git a/hosts/vault/vault.nix b/hosts/vault/vault.nix index 4c8b248..3f21d81 100644 --- a/hosts/vault/vault.nix +++ b/hosts/vault/vault.nix @@ -14,8 +14,6 @@ in { ./secrets.nix ]; - systemd.tmpfiles.rules = [ "d /secrets - root root" ]; - services.vault = { enable = true; package = pkgs.vault-bin; diff --git a/profiles/nginx.nix b/profiles/nginx.nix index cb2c645..67cac83 100644 --- a/profiles/nginx.nix +++ b/profiles/nginx.nix @@ -1,4 +1,4 @@ -{...}: { +{ ... }: { security.acme = { defaults = { email = "chaoticryptidz@owo.monster"; }; acceptTerms = true; @@ -13,4 +13,4 @@ clientMaxBodySize = "512m"; serverNamesHashBucketSize = 1024; }; -} \ No newline at end of file +} diff --git a/profiles/nix-gc.nix b/profiles/nix-gc.nix index 189c6b1..df7c466 100644 --- a/profiles/nix-gc.nix +++ b/profiles/nix-gc.nix @@ -5,4 +5,4 @@ dates = "daily"; options = "--delete-older-than 1d"; }; -} \ No newline at end of file +}