diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-04-30 19:34:25 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-04-30 19:34:25 +0200 |
commit | 5f21796b4a048bb4da1e00d6abe645dbb7cc6082 (patch) | |
tree | a9f95f851667403ce02cd4b54f59e61f3b46ea0d | |
parent | modules/lf/commands/trash_*: Add required `gnused` dependency (diff) | |
download | nixos-config-5f21796b4a048bb4da1e00d6abe645dbb7cc6082.zip |
modules/backup: Port to storagebox
-rw-r--r-- | hosts/apzu/default.nix | 4 | ||||
-rw-r--r-- | hosts/tiamat/default.nix | 4 | ||||
-rw-r--r-- | modules/by-name/ba/backup/module.nix | 98 | ||||
-rw-r--r-- | modules/common/default.nix | 6 | ||||
-rw-r--r-- | modules/common/secrets/backup/privatePassword.age | 14 | ||||
-rw-r--r-- | modules/common/secrets/backup/privateSshKey.age | 22 | ||||
-rw-r--r-- | secrets.nix | 3 |
7 files changed, 113 insertions, 38 deletions
diff --git a/hosts/apzu/default.nix b/hosts/apzu/default.nix index e700cb49..96dd99e1 100644 --- a/hosts/apzu/default.nix +++ b/hosts/apzu/default.nix @@ -18,10 +18,6 @@ ]; soispha = { - services.backup = { - # Apzu should be regularly synced with Tiamat, which performs updates. - enable = false; - }; bluetooth.enable = true; laptop = { diff --git a/hosts/tiamat/default.nix b/hosts/tiamat/default.nix index a1796a86..794b8390 100644 --- a/hosts/tiamat/default.nix +++ b/hosts/tiamat/default.nix @@ -31,10 +31,6 @@ systemName = "x86_64-linux"; }; services = { - backup = { - backupDiskUuid = "c06ce163-2955-4388-b212-dfec4448fcf4"; - enable = true; - }; unison.foreign.address = "apzu.fritz.box"; }; programs = { diff --git a/modules/by-name/ba/backup/module.nix b/modules/by-name/ba/backup/module.nix index 95abcb14..63186e91 100644 --- a/modules/by-name/ba/backup/module.nix +++ b/modules/by-name/ba/backup/module.nix @@ -9,50 +9,88 @@ # If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. { lib, - pkgs, config, + pkgs, ... }: let - backup-script = pkgs.writeShellScriptBin "backsnap" '' - set -xeu; - - ${pkgs.util-linux}/bin/mount --mkdir "/dev/disk/by-uuid/${cfg.backupDiskUuid}" "/run/media/${cfg.backupDiskUuid}"; - ${pkgs.snap-sync-forked}/bin/snap-sync-forked --UUID "${cfg.backupDiskUuid}" --noconfirm; - ${pkgs.util-linux}/bin/umount "/run/media/${cfg.backupDiskUuid}"; - ''; - cfg = config.soispha.services.backup; in { options.soispha.services.backup = { - enable = lib.mkEnableOption "backups with my forked snap-sync"; - backupDiskUuid = lib.mkOption { + enable = lib.mkEnableOption "backups via restic to a storagebox"; + + user = lib.mkOption { type = lib.types.str; - example = lib.literalExpression "d1d20ae7-3d8a-44da-86da-677dbbb10c89"; - description = "The UUID of the backup disk"; + description = "The storagebox-user to use"; + example = "u384702-sub2"; + }; + privateSshKey = lib.mkOption { + type = lib.types.path; + description = "The age-encrypted ssh-key, passed to agenix"; + }; + privatePassword = lib.mkOption { + type = lib.types.path; + description = "The age-encrypted restic password, passed to agenix"; }; }; config = lib.mkIf cfg.enable { - systemd = { - services.backup = { - wantedBy = lib.mkForce []; - unitConfig = { - Description = "Backup the last snapshots of the persitent-storage subvolume."; - }; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${backup-script}/bin/backsnap"; - }; + age.secrets = { + resticpass = { + file = cfg.privatePassword; + mode = "0700"; + owner = "root"; + group = "root"; }; + resticssh = { + file = cfg.privateSshKey; + mode = "0700"; + owner = "root"; + group = "root"; + }; + }; + + services.restic.backups = let + snapshotDir = "/srv/snapshots"; + homeDir = "${snapshotDir}/home"; + in { + storagebox = { + initialize = true; + backupPrepareCommand = + # bash + '' + [ -d /srv/snapshots/home ] && ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume delete /srv/snapshots/home; + + # -r := Make the snapshot read-only + ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume snapshot -r /home /srv/snapshots/home; + + [ -d /srv/snapshots/srv ] && ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume delete /srv/snapshots/srv; + ${lib.getExe' pkgs.btrfs-progs "btrfs"} subvolume snapshot -r /srv /srv/snapshots/srv; + ''; + paths = [ + snapshotDir + ]; + exclude = [ + "${homeDir}/soispha/.cache" + ]; + extraBackupArgs = [ + "--verbose" # Spam log + ]; + + passwordFile = config.age.secrets.resticpass.path; + extraOptions = [ + "rclone.program='ssh -p 23 ${cfg.user}@${cfg.user}.your-storagebox.de -i ${config.age.secrets.resticssh.path} command_forced_on_remote'" + ]; + + # This setting is normally passed to rclone, but we force + # the command on the remote. + # As such, the value does not matter and must only be parseable by restic. + repository = "rclone: "; - timers.backup = { - wantedBy = ["timers.target"]; - unitConfig = { - Description = "Backup 15min after boot and every 8 hours"; - }; timerConfig = { - OnBootSec = "15min"; - OnUnitActiveSec = "8h"; + Requires = "network-online.target"; + OnActiveSec = "30m"; + OnUnitInactiveSec = "2h"; + Persistent = true; }; }; }; diff --git a/modules/common/default.nix b/modules/common/default.nix index 393979d1..893ffab5 100644 --- a/modules/common/default.nix +++ b/modules/common/default.nix @@ -45,6 +45,12 @@ enable = true; user = "soispha"; }; + backup = { + enable = true; + user = "u459143-sub1"; + privateSshKey = ./secrets/backup/privateSshKey.age; + privatePassword = ./secrets/backup/privatePassword.age; + }; fwupd.enable = true; mpd = { enable = true; diff --git a/modules/common/secrets/backup/privatePassword.age b/modules/common/secrets/backup/privatePassword.age new file mode 100644 index 00000000..a2aa984a --- /dev/null +++ b/modules/common/secrets/backup/privatePassword.age @@ -0,0 +1,14 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzbnJ5Z3NXRFRtdEdCNk1z +NG9Cb2FUTEZ2U2hTdUptWGpneHd2RGxGQlY0ClhqcHlMSUZlLzBPZko4a2hKdnE1 +Q1hnc3ErWlJiSk1HVXFLcSswQlV0WTAKLT4gc3NoLWVkMjU1MTkgelpFb25nIG5I +cFpMY21ZdU9TUHY5VksraG1xeFByQlM1WE1INEk0SWFJQzIvSXhZbXMKSWxiNlIr +NjZ6bEgySUJGdnpoZTY2MmxxajJMaUVTM3RkTmhpdkxaRnNCQQotPiBzc2gtZWQy +NTUxOSA3SGZGVXcgRGtLMHFORm9mUDUwZnBXM0djcFlxTExJbWVDeDJmbVVSRi9l +QTFmekpROApZY3Z0Zlc1SUdCcllKQ01ZNmdFQkI3UnViVGxzNTJNUkhqc2hOejY3 +MndrCi0+IG1Hbi1ncmVhc2UgUDJJdgpGUmVHa1NPWGtzUmZmMXM3eWkxVnJkek1h +MUxZeS9qMlArendXZ1ltdFgvMTBabTlPM2hzSjhuVXBQNktHKzc1ClF6bjZob09B +Ci0tLSB3dEZpbnpVR0pPdGpFVmNyM0JzUGl6eGcreXpkTG9xQUc5S09ndUthaEpR +CuHgXCIq/AUCuIQWepBRapAab6zczOwxEBpDv5R2kw2mw34UVRLuFs7hB1cHE79y +7Fc= +-----END AGE ENCRYPTED FILE----- diff --git a/modules/common/secrets/backup/privateSshKey.age b/modules/common/secrets/backup/privateSshKey.age new file mode 100644 index 00000000..a7f30c7c --- /dev/null +++ b/modules/common/secrets/backup/privateSshKey.age @@ -0,0 +1,22 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJOTFaQVpnQ2VJN1pJbmdu +STF2UTF1Y3lyU2p3OUJlcWRFWlg3Mm9vSEFFCjg4RklaZ0hqdWdZSlJ0dGx0ckJN +eHE4R1QyTEJEVkZudnVQV2VpblBYTW8KLT4gc3NoLWVkMjU1MTkgelpFb25nIDR0 +Z2RwTXJGV1VYT2Y1OUcxbXpnOGNEbG9BWmFxeWUzZ1huNW1YQk5BM3cKK1hLNnYx +VnNvRDZWM3Y4VUpCQTRtbHJOcDJLdTBOUXJ1ak52Mkp3TE9OcwotPiBzc2gtZWQy +NTUxOSA3SGZGVXcgSHFSOXM1Vm1lY0ErRkZobndEU0xvQjVXbnhDbUlGNmE2dStY +SEFqSk9TMAo2VU5UbW9rc29kendvcHNuU3hFQ2lBQWNjRUxUSE10RmtjbkdwWGlv +cTRVCi0+IDwtZ3JlYXNlIHNPT3N1IHNkZzcoQzUgLUM3Ml1Tcgorb3FQcWlDSkJQ +L1g4WisydkYxdnJMeDNISVVDTGlZdmUyRkV0TkFUdW4ycXZBSlF3UWM2R3FTYjRs +ckEyaTg2ClVrbwotLS0gdHF5Q3BqV3h2TzEySCs4OFNIYmx1U0hsTWo1RDlTV3VC +T1RmelZaWXh4YwoeRkYbirDGX9aZj6OVxZ8sVsm2Sz23ikcBhAdTIXKErM7eQcdp +Y2nA5kUebPVznbSq/XSQNbqvCfSv9wVVTZWww7AqkrltjFS8yxQVMKB37IfnJsZI +92OCjJKArxAbvS7ERKY51Cf9oY/VqGk5WqxExH5ZvdbL144UI8JzrxhDopVXBWNd +fCrHirRAdlu3wgVILXV3vk1kmE69sspuV4cer5f/kOBKT1w09s2NFFHH4TO3cLTJ +Obgi/HWYHBjqGSgwd4bDtNOW2UDE1LN3YeUhloutWhuX8yt+NFzZJtl+CBrRqLKA +0CK+ZPKPWWKYPCNlzKT4vDF9BZeyCfoEj9dTXvxrNPEB6YYi16aQ8DhI8wxADl41 +ShrULlEmB8rfz7V+8TFmERKISBRSSH0p+XJi8e2DWh2dSco16rizmbFFNDdcYiGT +WWbXYCFNzj+kNFI/vEtt9dEWmfXlgg01khnyoOuRLedtoCDSuF+8z7YYy6oYt/2h +gmf4NHOUgyxK56c17JMQ3xT97d2odgqmwB+YZQ13IJCjt3M3pmSssD4sTgmA5alH +vtUlci6dZdO801h5vOesbAJplXCEyw== +-----END AGE ENCRYPTED FILE----- diff --git a/secrets.nix b/secrets.nix index 4757ced4..8b4a5545 100644 --- a/secrets.nix +++ b/secrets.nix @@ -17,6 +17,9 @@ in { "modules/by-name/ta/taskwarrior/secrets/sync_server_encryption_key.age".publicKeys = [soispha tiamat apzu]; + "modules/common/secrets/backup/privateSshKey.age".publicKeys = [soispha tiamat apzu]; + "modules/common/secrets/backup/privatePassword.age".publicKeys = [soispha tiamat apzu]; + "modules/by-name/se/serverphone/private_keys/ca.key".publicKeys = [soispha tiamat apzu]; "modules/by-name/se/serverphone/private_keys/server.key".publicKeys = [soispha tiamat apzu]; } |