From a10d48d007a4a88af662283b040aab1953efb50d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=91=D0=B5=D0=BB=D0=BE?= =?UTF-8?q?=D1=83=D1=81=D0=BE=D0=B2?= Date: Thu, 26 Feb 2026 08:24:40 +0300 Subject: [PATCH] Add backups --- hosts/server/configuration.nix | 105 +++++++++++++++++++++++---------- secrets.nix | 9 ++- secrets/restic-environment.age | 7 +++ secrets/restic-password.age | 8 +++ 4 files changed, 94 insertions(+), 35 deletions(-) create mode 100644 secrets/restic-environment.age create mode 100644 secrets/restic-password.age diff --git a/hosts/server/configuration.nix b/hosts/server/configuration.nix index 54341d4..965f73f 100644 --- a/hosts/server/configuration.nix +++ b/hosts/server/configuration.nix @@ -1,11 +1,23 @@ -{ ... }: +{ pkgs, config, ... }: let myKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIArRfRumAbMcRypGundddfVg7t+VOwVeQ+HUQfI9AFbX flygrounder@home"; + stalwartCaddyCertsDir = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.flygrounder.ru"; + stalwartCertsDir = "/var/lib/stalwart-mail/certs"; in { - age.secrets.stalwart-admin-password = { - file = ../../secrets/stalwart-admin-password.age; - owner = "stalwart-mail"; + age.secrets = { + stalwart-admin-password = { + file = ../../secrets/stalwart-admin-password.age; + owner = "stalwart-mail"; + }; + restic-environment = { + file = ../../secrets/restic-environment.age; + owner = "root"; + }; + restic-password = { + file = ../../secrets/restic-password.age; + owner = "root"; + }; }; users.users = { @@ -21,6 +33,8 @@ in }; }; + environment.systemPackages = with pkgs; [ restic ]; + home-manager.users.flygrounder.custom = { catppuccin.enable = true; cli.enable = true; @@ -129,37 +143,27 @@ in }; }; - systemd.paths.stalwart-certs = { - wantedBy = [ "multi-user.target" ]; - pathConfig = { - PathModified = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.flygrounder.ru/mail.flygrounder.ru.crt"; + systemd = { + paths.stalwart-certs = { + wantedBy = [ "multi-user.target" ]; + pathConfig = { + PathModified = "${stalwartCaddyCertsDir}/mail.flygrounder.ru.crt"; + }; + }; + services.stalwart-certs = { + serviceConfig = { + Type = "oneshot"; + }; + script = '' + mkdir -p ${stalwartCertsDir} + cp -L ${stalwartCaddyCertsDir}/*.{key,crt} ${stalwartCertsDir}/ + chown stalwart-mail:stalwart-mail ${stalwartCertsDir}/* + chmod 600 ${stalwartCertsDir}/* + systemctl restart stalwart + ''; }; }; - systemd.services.stalwart-certs = { - after = [ "caddy.service" ]; - before = [ "stalwart.service" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "oneshot"; - }; - script = '' - mkdir -p /var/lib/stalwart-mail/certs - cp -L /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.flygrounder.ru/mail.flygrounder.ru.crt /var/lib/stalwart-mail/certs/ - cp -L /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.flygrounder.ru/mail.flygrounder.ru.key /var/lib/stalwart-mail/certs/ - chown stalwart-mail:stalwart-mail /var/lib/stalwart-mail/certs/* - chmod 600 /var/lib/stalwart-mail/certs/* - ''; - postStop = '' - if systemctl is-active --quiet stalwart.service; then - systemctl --no-block restart stalwart.service - fi - ''; - }; - - systemd.services.stalwart.after = [ "stalwart-certs.service" ]; - systemd.services.stalwart.requires = [ "stalwart-certs.service" ]; - imports = [ ./hardware-configuration.nix ./disko-config.nix @@ -192,4 +196,41 @@ in interface = "ens3"; }; }; + + services.restic.backups = + let + mkBackup = + { service, path }: + { + paths = [ + path + ]; + repository = "s3:https://s3.firstvds.ru/flygrounder-backups/${service}"; + initialize = true; + timerConfig = { + OnCalendar = "03:00"; + Persistent = true; + RandomizedDelaySec = "10m"; + }; + environmentFile = "/run/agenix/restic-environment"; + passwordFile = "/run/agenix/restic-password"; + backupPrepareCommand = "systemctl stop ${service}"; + backupCleanupCommand = "systemctl start ${service}"; + pruneOpts = [ + "--keep-daily 14" + "--keep-weekly 4" + "--keep-monthly 2" + ]; + }; + in + { + stalwart = mkBackup { + service = "stalwart"; + path = config.services.stalwart.dataDir; + }; + vaultwarden = mkBackup { + service = "vaultwarden"; + path = "/var/lib/vaultwarden"; + }; + }; } diff --git a/secrets.nix b/secrets.nix index c886d02..b612b1d 100644 --- a/secrets.nix +++ b/secrets.nix @@ -1,7 +1,10 @@ let - flygrounder = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIArRfRumAbMcRypGundddfVg7t+VOwVeQ+HUQfI9AFbX flygrounder@home"; - server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOO6lKCmpKEarta4hBOcjHWznpf/RbCWuLS88/ZV1OeX root@nixos"; + myKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIArRfRumAbMcRypGundddfVg7t+VOwVeQ+HUQfI9AFbX flygrounder@home"; + serverKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOO6lKCmpKEarta4hBOcjHWznpf/RbCWuLS88/ZV1OeX root@nixos"; + keys = [myKey serverKey]; in { - "secrets/stalwart-admin-password.age".publicKeys = [ flygrounder server ]; + "secrets/stalwart-admin-password.age".publicKeys = keys; + "secrets/restic-password.age".publicKeys = keys; + "secrets/restic-environment.age".publicKeys = keys; } diff --git a/secrets/restic-environment.age b/secrets/restic-environment.age new file mode 100644 index 0000000..273d055 --- /dev/null +++ b/secrets/restic-environment.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 hPdT4Q P/PkpF8ZunYU986z3F23eS+Le+9qIpCOrxNtvArjxBA +nRXQMF56aMcYD+917WzQho75/Fxcj0AGvyTDSv+mOow +-> ssh-ed25519 HTO34g 4gI4dU68GE6eJhJqmzNszHPfd1ll0LpTSoxPCBJMq18 +vqSq71zfLjHtZOQCE/nUFoTSEAoAMemJTsPCpzIgNOE +--- +DAhJCj0seJziB77lUSxk1e+WOZ8bEdFLBthEDXj66s +£'íÒž,–¯´šŽÕªSü²½=5½—z"s#¤e¨—B¥¢\á¡ywÀWú<›®V˜ô‡+zÎÁËS ˆiGb‡bŸQW èV¨ŽŒ#d¾¶Ñl2³’'vØ‚—ÃfQàg?\ ;7,geˆP¡Ã^ÂZ/¨c)ø3<%v>ÞJ{QJà÷VþŸ \ No newline at end of file diff --git a/secrets/restic-password.age b/secrets/restic-password.age new file mode 100644 index 0000000..e2a2963 --- /dev/null +++ b/secrets/restic-password.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 hPdT4Q ZStPwiiUAdNIErKk6D9g/YpjUBfGZgQ/RAwTx5opaVk +erkWmVTtYx3x0a75jqOfj7wCoeytWlWeLNvGYRiLO6M +-> ssh-ed25519 HTO34g ntboG9TiiruRXaoZCou8DvKyAsojKoBMOa3Xguple0A +rcMwGjzc0a0AwBskdtpYB3vV0iNeZjiS5RmeGy2NUrc +--- mcqZgUYYx5jhBoZhLOKNh7kFB/aElVFHtJ7Ww4cPQ5Y +ä $ZøYZg…½dãng17XMdêÞ½Y +ï"u<Êx;~Ȇll:¢fOà2úz`±¸*ío¾½ZK2 \ No newline at end of file