diff --git a/hosts/nixos/noximilien/configuration.nix b/hosts/nixos/noximilien/configuration.nix index 98d22de..2ce48d5 100644 --- a/hosts/nixos/noximilien/configuration.nix +++ b/hosts/nixos/noximilien/configuration.nix @@ -31,6 +31,9 @@ # ../../../profiles/services/tmate-server.nix # opens port 42244 # TODO: move outside of home net + # TODO: + # ../../../profiles/backup + ../../../profiles/http # enables nginx+acme, defines mkDomain ../../../profiles/http/index # ../../../profiles/http/services/cache-proxy diff --git a/profiles/backup/default.nix b/profiles/backup/default.nix new file mode 100644 index 0000000..09b38f8 --- /dev/null +++ b/profiles/backup/default.nix @@ -0,0 +1,110 @@ +{ config, lib, ... }: + +let + notInVM = lib.mkIf (!config.virtualisation.isVmVariant); + inherit (config.networking) hostName; + sopsFile = lib.mkDefault ../../hosts/nixos/${hostName}/secrets.yaml; +in + +{ + options = { + pbsds.backup.paths = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + }; + }; + + imports = lib.map notInVM [ + ./postgres.nix + ]; + + config = notInVM { + + # https://restic.readthedocs.io/en/latest/070_encryption.html#manage-repository-keys + + sops.secrets = { + # $ sops --set '["restic_systems_password_meconium"] "'$(pwgen --ambiguous --secure 64 1)'"' hosts/nixos/$(nix eval .#nixosConfigurations --apply builtins.attrNames --json | jq .[] -r | xargs gum choose)/secrets.yaml + restic_systems_password_meconium.sopsFile = sopsFile; + + # $ sops --set '["restic_systems_password_panorama"] "'$(pwgen --ambiguous --secure 64 1)'"' hosts/nixos/$(nix eval .#nixosConfigurations --apply builtins.attrNames --json | jq .[] -r | xargs gum choose)/secrets.yaml + restic_systems_password_panorama.sopsFile = sopsFile; + + # # https://restic.readthedocs.io/en/latest/040_backup.html#environment-variables + restic_systems_password_s3.sopsFile = sopsFile; + restic_systems_environment_s3.sopsFile = sopsFile; + }; + + services.restic.backups = + let + shared = { + initialize = true; + # createWrapper = true; # adds a "restic-${name}" wrapper in system path + + # TODO: --skip-if-unchanged ? + paths = [ "/var/lib" ] ++ config.pbsds.backup.paths; + timerConfig.OnCalendar = "hourly"; + pruneOpts = [ + "--keep-daily 5" + "--keep-weekly 3" + "--keep-monthly 2" + ]; + }; + in + { + "systems-meconium" = shared // { + # repository = "sftp:noximilien:/mnt/meconium/Backups/restic/system-${hostName}"; + repository = "sftp:noximilien:/mnt/meconium/Backups/restic/systems"; + passwordFile = config.sops.secrets.restic_systems_password_meconium.path; + # environmentFile = config.sops.secrets.restic_systems_environment_meconium.path; + }; + + "systems-panorama" = shared // { + # repository = "sftp:eple:/mnt/panorama/Backups/restic/system-${hostName}"; + repository = "sftp:eple:/mnt/panorama/Backups/restic/systems"; + passwordFile = config.sops.secrets.restic_systems_password_panorama.path; + # environmentFile = config.sops.secrets.restic_systems_environment_panorama.path; + }; + + # "systems-b2" = shared // { + # repository = "s3:1246890.r2.cloudflarestorage.com/restic-systems"; + # passwordFile = config.sops.secrets.restic_systems_password_s3.path; + # environmentFile = config.sops.secrets.restic_systems_environment_s3.path; + # }; + }; + + # backup of user homes + + /* + TODO = lib.pip config.users.users [ + lib.attrNames + (lib.filter (user: config.users.users.${user}.enable)) + (lib.filter (user: config.users.users.${user}.isNormalUser)) + # (lib.filter (user: config.users.users.${user}.createHome)) + (lib.map (user: + { + # sops.secrets.restic_user_${user}_password_meconium.owner = user; + # sops.secrets.restic_user_${user}_password_meconium.sopsFile = sopsFile; + + services.restic.backups."user-${user}" = { + inherit (config.services.restic.backups."system") + initialize + pruneOpts + timerConfig + ; + + # createWrapper = true; # adds a "restic-${name}" wrapper in system path + + inherit user; # the user can see this password, hence we must use per-user restic repositories + passwordFile = config.sops.secrets.restic_user_${user}_password_meconium.path; + # environmentFile = config.sops.secrets.restic_user_${user}_environment_meconium.path; + + paths = [ config.users.users.${user}.home ]; + repository = "sftp:noximilien/mnt/meconium/Backups/restic/user-${user}"; + }; + } + )) + ]; + */ + + }; +} diff --git a/profiles/backup/postgres.nix b/profiles/backup/postgres.nix new file mode 100644 index 0000000..2b21606 --- /dev/null +++ b/profiles/backup/postgres.nix @@ -0,0 +1,17 @@ +{ lib, config, ... }: +let + mkIf = lib.mkIf config.services.postgresql.enable; +in +{ + + pbsds.backup.paths = mkIf [ config.postgresqlBackup.location ]; # "/var/backup/postgresql" + + services.postgresqlBackup = mkIf { + enable = true; + # databases = [ "foo" ]; + backupAll = true; # default if no databases are specified, mutually exclusive + compression = "none"; # Let restic handle the compression, enabling de-duplication + # startAt = "*-*-* 01:15:00"; # nightly (default) + }; + +}