From fefb810d97c844f5c0211748bf52ccf4434053b0 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Mon, 27 May 2024 13:38:44 +0300 Subject: [PATCH] Set up restic on all hosts --- .gitignore | 2 +- hosts/cube/default.nix | 6 +++++ hosts/cube/forgejo/default.nix | 4 +++ hosts/cube/grafana/default.nix | 4 +++ hosts/cube/matrix/default.nix | 4 +++ hosts/cube/nextcloud/default.nix | 4 +++ hosts/cube/postgresql.nix | 16 +++++++++++- hosts/cube/restic/default.nix | 44 -------------------------------- hosts/cube/restic/password.age | 9 ------- hosts/disk/default.nix | 2 +- hosts/disk/mail/default.nix | 4 +++ hosts/nine/default.nix | 6 +++++ keys.nix | 17 +++++++----- modules/restic/default.nix | 27 ++++++++++++++++++++ secrets.nix | 33 ++++++++++-------------- 15 files changed, 100 insertions(+), 82 deletions(-) delete mode 100644 hosts/cube/restic/default.nix delete mode 100644 hosts/cube/restic/password.age create mode 100644 modules/restic/default.nix diff --git a/.gitignore b/.gitignore index 7004820..e81c63e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ !hosts/cube/grafana/ !hosts/cube/matrix/ !hosts/cube/nextcloud/ -!hosts/cube/restic/ !hosts/disk/ !hosts/disk/mail/ @@ -22,6 +21,7 @@ !modules/ !modules/hyprland/ !modules/nushell/ +!modules/restic/ !modules/ssh/ !lib/ diff --git a/hosts/cube/default.nix b/hosts/cube/default.nix index ce9726e..a3ad066 100644 --- a/hosts/cube/default.nix +++ b/hosts/cube/default.nix @@ -15,6 +15,12 @@ openssh.authorizedKeys.keys = [ keys.enka ]; hashedPasswordFile = config.secrets.rgbPassword.path; }; + + backup = normalUser { + description = "Backup"; + openssh.authorizedKeys.keys = keys.all; + hashedPasswordFile = config.secrets.rgbPassword.path; + }; }; services.openssh = { diff --git a/hosts/cube/forgejo/default.nix b/hosts/cube/forgejo/default.nix index 7244ccb..e5b4a2f 100644 --- a/hosts/cube/forgejo/default.nix +++ b/hosts/cube/forgejo/default.nix @@ -24,6 +24,10 @@ in systemConfiguration { }]; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ "/var/lib/gitea-runner" "/var/lib/forgejo" ]; + }); + users.groups.gitea-runner = {}; users.users.gitea-runner = systemUser { extraGroups = [ "docker" ]; diff --git a/hosts/cube/grafana/default.nix b/hosts/cube/grafana/default.nix index c603479..75c469c 100644 --- a/hosts/cube/grafana/default.nix +++ b/hosts/cube/grafana/default.nix @@ -24,6 +24,10 @@ in systemConfiguration { }]; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ "/var/lib/grafana" ]; + }); + systemd.services.grafana = { after = [ "postgresql.service" ]; requires = [ "postgresql.service" ]; diff --git a/hosts/cube/matrix/default.nix b/hosts/cube/matrix/default.nix index b100275..d159b0c 100644 --- a/hosts/cube/matrix/default.nix +++ b/hosts/cube/matrix/default.nix @@ -59,6 +59,10 @@ in serverSystemConfiguration { ]; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ "/var/lib/matrix-synapse" "/var/lib/matrix-sliding-sync" ]; + }); + services.matrix-synapse = enabled { withJemalloc = true; diff --git a/hosts/cube/nextcloud/default.nix b/hosts/cube/nextcloud/default.nix index 9cbc92d..176a297 100644 --- a/hosts/cube/nextcloud/default.nix +++ b/hosts/cube/nextcloud/default.nix @@ -32,6 +32,10 @@ in systemConfiguration { }]; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ "/var/lib/nextcloud" ]; + }); + systemd.services.nextcloud-setup = { after = [ "postgresql.service" ]; requires = [ "postgresql.service" ]; diff --git a/hosts/cube/postgresql.nix b/hosts/cube/postgresql.nix index a09164a..149bca8 100644 --- a/hosts/cube/postgresql.nix +++ b/hosts/cube/postgresql.nix @@ -1,4 +1,4 @@ -{ lib, pkgs, ... }: with lib; merge +{ config, lib, pkgs, ... }: with lib; merge (systemConfiguration { services.prometheus.exporters.postgres = enabled { @@ -6,6 +6,20 @@ runAsLocalSuperUser = true; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ "/tmp/postgresql-dump.sql.gz" ]; + + backupPrepareCommand = '' + ${config.services.postgresql.package}/bin/pg_dumpall --clean \ + | ${lib.getExe pkgs.gzip} --rsyncable \ + > /tmp/postgresql-dump.sql.gz + ''; + + backupCleanupCommand = '' + rm /tmp/postgresql-dump.sql.gz + ''; + }); + services.postgresql = enabled { package = pkgs.postgresql_14; diff --git a/hosts/cube/restic/default.nix b/hosts/cube/restic/default.nix deleted file mode 100644 index 8865125..0000000 --- a/hosts/cube/restic/default.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ config, lib, pkgs, ... }: with lib; - -systemConfiguration { - secrets.resticPassword.file = ./password.age; - - services.restic.backups.disk = { - repository = "sftp:backup@disk:${config.networking.hostName}-backup"; - passwordFile = config.secrets.resticPassword.path; - initialize = true; - - pruneOpts = [ - "--keep-daily unlimited" - "--keep-weekly unlimited" - "--keep-monthly 6" - "--keep-yearly 12" - ]; - - timerConfig = { - OnCalendar = "daily"; - Persistent = true; - }; - - paths = [ - "/tmp/postgresql-dump.sql.gz" - ] ++ map (dir: "/var/lib/${dir}") [ - "forgejo" - "gitea-runner" - "grafana" - "matrix-sliding-sync" - "matrix-synapse" - "nextcloud" - ]; - - backupPrepareCommand = '' - ${config.services.postgresql.package}/bin/pg_dumpall --clean \ - | ${lib.getExe pkgs.gzip} --rsyncable \ - > /tmp/postgresql-dump.sql.gz - ''; - - backupCleanupCommand = '' - rm /tmp/postgresql-dump.sql.gz - ''; - }; -} diff --git a/hosts/cube/restic/password.age b/hosts/cube/restic/password.age deleted file mode 100644 index a9e67bc..0000000 --- a/hosts/cube/restic/password.age +++ /dev/null @@ -1,9 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 +rZ0Tw JhqOkh+PwYHVBthp3sK8ObXpilu/Fn8sDelDyk9ShkI -Q93HHN68Sq3g+dvPLi/uw/w6Uzsqi39rPwV8hitl1dM --> ssh-ed25519 CzqbPQ R+z/ARbQuV0B4fZ/f/4Z7LQCofg0VbagNymI2VkRv38 -/WEmH+UdUQ3u3IACisaYIhJ0u8fiJP/hjPd6UkN5c8k --> ssh-ed25519 f5VzMA FrgY7EJzi5ZtdxA8bIZZG5Q1L7Abrx0wWyVKOGreRgU -OWTnpJl9Yt14H9tzLxFxZqksADe4fAESWQ2ebZt/vMg ---- jjnpTS1CXY89cYNu90SL5kVJ8ddo7Twabb9TWIyaYMw -},="T/y:߈l;/[je@e` \ No newline at end of file diff --git a/hosts/disk/default.nix b/hosts/disk/default.nix index a192dfe..44b7e1d 100644 --- a/hosts/disk/default.nix +++ b/hosts/disk/default.nix @@ -18,7 +18,7 @@ backup = normalUser { description = "Backup"; - openssh.authorizedKeys.keys = [ keys.cube keys.enka ]; + openssh.authorizedKeys.keys = keys.all; hashedPasswordFile = config.secrets.floppyPassword.path; }; }; diff --git a/hosts/disk/mail/default.nix b/hosts/disk/mail/default.nix index 0dedec0..d685621 100644 --- a/hosts/disk/mail/default.nix +++ b/hosts/disk/mail/default.nix @@ -13,6 +13,10 @@ in systemConfiguration { listenAddress = "[::]"; }; + services.restic.backups = genAttrs config.resticHosts (_: { + paths = [ config.mailserver.dkimKeyDirectory config.mailserver.mailDirectory ]; + }); + mailserver = enabled { fqdn = mkDefault fqdn; diff --git a/hosts/nine/default.nix b/hosts/nine/default.nix index c330da1..6f6383c 100644 --- a/hosts/nine/default.nix +++ b/hosts/nine/default.nix @@ -15,6 +15,12 @@ openssh.authorizedKeys.keys = [ keys.enka ]; hashedPasswordFile = config.secrets.sevenPassword.path; }; + + backup = normalUser { + description = "Backup"; + openssh.authorizedKeys.keys = keys.all; + hashedPasswordFile = config.secrets.sevenPassword.path; + }; }; services.openssh.hostKeys = [{ diff --git a/keys.nix b/keys.nix index d20d5eb..f22e064 100644 --- a/keys.nix +++ b/keys.nix @@ -1,7 +1,12 @@ -{ - cube = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMkCJeHcD0SIOZ4HkyF6rqUmbvlKhSha3HWMZ0hbIjp rgb@cube"; - disk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItpYQ3Pz6zFifKXvFX7xAC8aby9RW/m5PkW8T9SOee4 floppy@disk"; - enka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkWUQ6Z4OK539tore/R5wnueNPPaX532RUAld8UOCo said@enka"; - pala = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEXXxaxhkIMy0UyLOOnvwkNjzypS7D9kElHGKw8pZuFb said@pala"; - nine = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJDqnItmvXZMTSwzbalr+9jzS4kSJm5PWEpI8GOpebF seven@nine"; +let + keys = { + cube = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMkCJeHcD0SIOZ4HkyF6rqUmbvlKhSha3HWMZ0hbIjp rgb@cube"; + disk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItpYQ3Pz6zFifKXvFX7xAC8aby9RW/m5PkW8T9SOee4 floppy@disk"; + enka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkWUQ6Z4OK539tore/R5wnueNPPaX532RUAld8UOCo said@enka"; + pala = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEXXxaxhkIMy0UyLOOnvwkNjzypS7D9kElHGKw8pZuFb said@pala"; + nine = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJDqnItmvXZMTSwzbalr+9jzS4kSJm5PWEpI8GOpebF seven@nine"; + }; +in keys // { + admins = [ keys.enka keys.pala ]; + all = builtins.attrValues keys; } diff --git a/modules/restic/default.nix b/modules/restic/default.nix new file mode 100644 index 0000000..dccd280 --- /dev/null +++ b/modules/restic/default.nix @@ -0,0 +1,27 @@ +{ config, lib, ... }: with lib; + +serverSystemConfiguration { + options.resticHosts = mkConst (remove config.networking.hostName [ "cube" "disk" "nine" ]); + + config = { + secrets.resticPassword.file = ./password.age; + + services.restic.backups = genAttrs config.resticHosts (host: { + repository = "sftp:backup@${host}:${config.networking.hostName}-backup"; + passwordFile = config.secrets.resticPassword.path; + initialize = true; + + pruneOpts = [ + "--keep-daily unlimited" + "--keep-weekly unlimited" + "--keep-monthly 6" + "--keep-yearly 12" + ]; + + timerConfig = { + OnCalendar = "daily"; + Persistent = true; + }; + }); + }; +} diff --git a/secrets.nix b/secrets.nix index 93bcc0f..c3a8756 100644 --- a/secrets.nix +++ b/secrets.nix @@ -1,31 +1,24 @@ -let - keys = import ./keys.nix; - - all = builtins.attrValues keys; - - admins = with keys; [ enka pala ]; - withAdmins = key: [ key ] ++ admins; -in with keys; { +with import ./keys.nix; { # cube - "hosts/cube/id.age".publicKeys = withAdmins cube; - "hosts/cube/password.rgb.age".publicKeys = withAdmins cube; + "hosts/cube/id.age".publicKeys = [ cube ] ++ admins; + "hosts/cube/password.rgb.age".publicKeys = [ cube ] ++ admins; "hosts/cube/acme/environment.age".publicKeys = all; - "hosts/cube/forgejo/password.runner.age".publicKeys = withAdmins cube; + "hosts/cube/forgejo/password.runner.age".publicKeys = [ cube ] ++ admins; - "hosts/cube/grafana/password.age".publicKeys = withAdmins cube; + "hosts/cube/grafana/password.age".publicKeys = [ cube ] ++ admins; - "hosts/cube/matrix/password.secret.age".publicKeys = withAdmins cube; - "hosts/cube/matrix/password.sync.age".publicKeys = withAdmins cube; + "hosts/cube/matrix/password.secret.age".publicKeys = [ cube ] ++ admins; + "hosts/cube/matrix/password.sync.age".publicKeys = [ cube ] ++ admins; - "hosts/cube/nextcloud/password.age".publicKeys = withAdmins cube; + "hosts/cube/nextcloud/password.age".publicKeys = [ cube ] ++ admins; - "hosts/cube/restic/password.age".publicKeys = withAdmins cube; + "hosts/cube/restic/password.age".publicKeys = [ cube ] ++ admins; # disk - "hosts/disk/id.age".publicKeys = withAdmins disk; - "hosts/disk/password.floppy.age".publicKeys = withAdmins disk; + "hosts/disk/id.age".publicKeys = [ disk ] ++ admins; + "hosts/disk/password.floppy.age".publicKeys = [ disk ] ++ admins; "hosts/disk/mail/password.plain.age".publicKeys = all; "hosts/disk/mail/password.hash.age".publicKeys = [ disk nine ] ++ admins; @@ -36,8 +29,8 @@ in with keys; { "hosts/enka/password.said.age".publicKeys = admins; # nine - "hosts/nine/id.age".publicKeys = withAdmins nine; - "hosts/nine/password.seven.age".publicKeys = withAdmins nine; + "hosts/nine/id.age".publicKeys = [ nine ] ++ admins; + "hosts/nine/password.seven.age".publicKeys = [ nine ] ++ admins; # shared "modules/ssh/config.age".publicKeys = all;