diff options
author | Peder Bergebakken Sundt <pbsds@hotmail.com> | 2023-10-26 19:35:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-26 19:35:22 +0200 |
commit | adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4 (patch) | |
tree | 6ad2abb78d22de5c9bd63ee6079b3812bf873fcc | |
parent | 020adc777c611c739c0f49099f4e6b9fb4f05aa3 (diff) | |
parent | 77bc27ccdb87b1a3400fc59f097f8218982a55ed (diff) | |
download | nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar.gz nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar.bz2 nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar.lz nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar.xz nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.tar.zst nixpkgs-adcaf3962d5147cec7d63c1ff9e3f7a3fe4653d4.zip |
Merge pull request #212087 from robryk/resticpaths
nixos/backups/restic: handle cases when both dynamicFileFrom and paths are set
-rw-r--r-- | nixos/modules/services/backup/restic.nix | 25 | ||||
-rw-r--r-- | nixos/tests/restic.nix | 18 |
2 files changed, 29 insertions, 14 deletions
diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix index 78220e99c3d..141eb4d07c4 100644 --- a/nixos/modules/services/backup/restic.nix +++ b/nixos/modules/services/backup/restic.nix @@ -113,12 +113,15 @@ in }; paths = mkOption { + # This is nullable for legacy reasons only. We should consider making it a pure listOf + # after some time has passed since this comment was added. type = types.nullOr (types.listOf types.str); - default = null; + default = [ ]; description = lib.mdDoc '' - Which paths to backup. If null or an empty array, no - backup command will be run. This can be used to create a - prune-only job. + Which paths to backup, in addition to ones specified via + `dynamicFilesFrom`. If null or an empty array and + `dynamicFilesFrom` is also null, no backup command will be run. + This can be used to create a prune-only job. ''; example = [ "/var/lib/postgresql" @@ -231,7 +234,7 @@ in description = lib.mdDoc '' A script that produces a list of files to back up. The results of this command are given to the '--files-from' - option. + option. The result is merged with paths specified via `paths`. ''; example = "find /home/matt/git -type d -name .git"; }; @@ -310,10 +313,7 @@ in resticCmd = "${backup.package}/bin/restic${extraOptions}"; excludeFlags = optional (backup.exclude != []) "--exclude-file=${pkgs.writeText "exclude-patterns" (concatStringsSep "\n" backup.exclude)}"; filesFromTmpFile = "/run/restic-backups-${name}/includes"; - backupPaths = - if (backup.dynamicFilesFrom == null) - then optionalString (backup.paths != null) (concatStringsSep " " backup.paths) - else "--files-from ${filesFromTmpFile}"; + doBackup = (backup.dynamicFilesFrom != null) || (backup.paths != null && backup.paths != []); pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [ (resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts)) (resticCmd + " check " + (concatStringsSep " " backup.checkOpts)) @@ -348,7 +348,7 @@ in after = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; - ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup ${concatStringsSep " " (backup.extraBackupArgs ++ excludeFlags)} ${backupPaths}" ]) + ExecStart = (optionals doBackup [ "${resticCmd} backup ${concatStringsSep " " (backup.extraBackupArgs ++ excludeFlags)} --files-from=${filesFromTmpFile}" ]) ++ pruneCmd; User = backup.user; RuntimeDirectory = "restic-backups-${name}"; @@ -366,8 +366,11 @@ in ${optionalString (backup.initialize) '' ${resticCmd} snapshots || ${resticCmd} init ''} + ${optionalString (backup.paths != null && backup.paths != []) '' + cat ${pkgs.writeText "staticPaths" (concatStringsSep "\n" backup.paths)} >> ${filesFromTmpFile} + ''} ${optionalString (backup.dynamicFilesFrom != null) '' - ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile} + ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} >> ${filesFromTmpFile} ''} ''; } // optionalAttrs (backup.dynamicFilesFrom != null || backup.backupCleanupCommand != null) { diff --git a/nixos/tests/restic.nix b/nixos/tests/restic.nix index 3b9ea2f85b1..54fdc1d3995 100644 --- a/nixos/tests/restic.nix +++ b/nixos/tests/restic.nix @@ -21,7 +21,10 @@ import ./make-test-python.nix ( unpackPhase = "true"; installPhase = '' mkdir $out - touch $out/some_file + echo some_file > $out/some_file + echo some_other_file > $out/some_other_file + mkdir $out/a_dir + echo a_file > $out/a_dir/a_file ''; }; @@ -53,9 +56,13 @@ import ./make-test-python.nix ( initialize = true; }; remote-from-file-backup = { - inherit passwordFile paths exclude pruneOpts; + inherit passwordFile exclude pruneOpts; initialize = true; repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository; + paths = [ "/opt/a_dir" ]; + dynamicFilesFrom = '' + find /opt -mindepth 1 -maxdepth 1 ! -name a_dir # all files in /opt except for a_dir + ''; }; rclonebackup = { inherit passwordFile paths exclude pruneOpts; @@ -123,13 +130,18 @@ import ./make-test-python.nix ( "systemctl start restic-backups-remote-from-file-backup.service", 'restic-remote-from-file-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"', + # test that restoring that snapshot produces the same directory + "mkdir /tmp/restore-2", + "${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} restore latest -t /tmp/restore-2", + "diff -ru ${testDir} /tmp/restore-2/opt", + # test that rclonebackup produces a snapshot "systemctl start restic-backups-rclonebackup.service", 'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"', # test that custompackage runs both `restic backup` and `restic check` with reasonable commandlines "systemctl start restic-backups-custompackage.service", - "grep 'backup.* /opt' /root/fake-restic.log", + "grep 'backup' /root/fake-restic.log", "grep 'check.* --some-check-option' /root/fake-restic.log", # test that we can create four snapshots in remotebackup and rclonebackup |