nixos/restic: add command option
Add module support for --stdin-from-command flag, which was added to restic in https://github.com/restic/restic/pull/4410. I also made a few very small changes here and there in the nix code to make it look a little neater in my opinion. I could potentially add support for the --stdin flag too, but this would require prepending the restic command with an external command and a pipe, which seems a bit messy - and the restic documentation says to prefer --stdin-from-command over --stdin anyway. I could add an option for --stdin-filename, but I feel that this would be better for users to do in extraBackupArgs.
This commit is contained in:
@@ -146,6 +146,21 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
command = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Command to pass to --stdin-from-command. If null or an empty array, and `paths`/`dynamicFilesFrom`
|
||||
are also null, no backup command will be run.
|
||||
'';
|
||||
example = [
|
||||
"sudo"
|
||||
"-u"
|
||||
"postgres"
|
||||
"pg_dumpall"
|
||||
];
|
||||
};
|
||||
|
||||
exclude = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
@@ -238,7 +253,7 @@ in
|
||||
|
||||
runCheck = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = (builtins.length config.services.restic.backups.${name}.checkOpts > 0);
|
||||
default = builtins.length config.services.restic.backups.${name}.checkOpts > 0;
|
||||
defaultText = lib.literalExpression ''builtins.length config.services.backups.${name}.checkOpts > 0'';
|
||||
description = "Whether to run the `check` command with the provided `checkOpts` options.";
|
||||
example = true;
|
||||
@@ -327,14 +342,44 @@ in
|
||||
RandomizedDelaySec = "5h";
|
||||
};
|
||||
};
|
||||
commandbackup = {
|
||||
command = [
|
||||
"\${lib.getExe pkgs.sudo}"
|
||||
"-u postgres"
|
||||
"\${pkgs.postgresql}/bin/pg_dumpall"
|
||||
];
|
||||
extraBackupArgs = [ "--tag database" ];
|
||||
repository = "s3:example.com/mybucket";
|
||||
passwordFile = "/etc/nixos/secrets/restic-password";
|
||||
environmentFile = "/etc/nixos/secrets/restic-environment";
|
||||
pruneOpts = [
|
||||
"--keep-daily 14"
|
||||
"--keep-weekly 4"
|
||||
"--keep-monthly 2"
|
||||
"--group-by tags"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = lib.mapAttrsToList (n: v: {
|
||||
assertion = (v.repository == null) != (v.repositoryFile == null);
|
||||
message = "services.restic.backups.${n}: exactly one of repository or repositoryFile should be set";
|
||||
}) config.services.restic.backups;
|
||||
assertions = lib.flatten (
|
||||
lib.mapAttrsToList (name: backup: [
|
||||
{
|
||||
assertion = (backup.repository == null) != (backup.repositoryFile == null);
|
||||
message = "services.restic.backups.${name}: exactly one of repository or repositoryFile should be set";
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
let
|
||||
fileBackup = (backup.paths != null && backup.paths != [ ]) || backup.dynamicFilesFrom != null;
|
||||
commandBackup = backup.command != [ ];
|
||||
in
|
||||
!(fileBackup && commandBackup);
|
||||
message = "services.restic.backups.${name}: cannot do both a command backup and a file backup at the same time.";
|
||||
}
|
||||
]) config.services.restic.backups
|
||||
);
|
||||
systemd.services = lib.mapAttrs' (
|
||||
name: backup:
|
||||
let
|
||||
@@ -351,7 +396,9 @@ in
|
||||
backup.exclude != [ ]
|
||||
) "--exclude-file=${pkgs.writeText "exclude-patterns" (lib.concatStringsSep "\n" backup.exclude)}";
|
||||
filesFromTmpFile = "/run/restic-backups-${name}/includes";
|
||||
doBackup = (backup.dynamicFilesFrom != null) || (backup.paths != null && backup.paths != [ ]);
|
||||
fileBackup = (backup.dynamicFilesFrom != null) || (backup.paths != null && backup.paths != [ ]);
|
||||
commandBackup = backup.command != [ ];
|
||||
doBackup = fileBackup || commandBackup;
|
||||
pruneCmd = lib.optionals (builtins.length backup.pruneOpts > 0) [
|
||||
(resticCmd + " unlock")
|
||||
(resticCmd + " forget --prune " + (lib.concatStringsSep " " backup.pruneOpts))
|
||||
@@ -397,11 +444,15 @@ in
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart =
|
||||
(lib.optionals doBackup [
|
||||
lib.optionals doBackup [
|
||||
"${resticCmd} backup ${
|
||||
lib.concatStringsSep " " (backup.extraBackupArgs ++ excludeFlags)
|
||||
} --files-from=${filesFromTmpFile}"
|
||||
])
|
||||
lib.concatStringsSep " " (
|
||||
backup.extraBackupArgs
|
||||
++ lib.optionals fileBackup (excludeFlags ++ [ "--files-from=${filesFromTmpFile}" ])
|
||||
++ lib.optionals commandBackup ([ "--stdin-from-command=true --" ] ++ backup.command)
|
||||
)
|
||||
}"
|
||||
]
|
||||
++ pruneCmd
|
||||
++ checkCmd;
|
||||
User = backup.user;
|
||||
@@ -419,7 +470,7 @@ in
|
||||
${lib.optionalString (backup.backupPrepareCommand != null) ''
|
||||
${pkgs.writeScript "backupPrepareCommand" backup.backupPrepareCommand}
|
||||
''}
|
||||
${lib.optionalString (backup.initialize) ''
|
||||
${lib.optionalString backup.initialize ''
|
||||
${resticCmd} cat config > /dev/null || ${resticCmd} init
|
||||
''}
|
||||
${lib.optionalString (backup.paths != null && backup.paths != [ ]) ''
|
||||
@@ -435,7 +486,7 @@ in
|
||||
${lib.optionalString (backup.backupCleanupCommand != null) ''
|
||||
${pkgs.writeScript "backupCleanupCommand" backup.backupCleanupCommand}
|
||||
''}
|
||||
${lib.optionalString doBackup ''
|
||||
${lib.optionalString fileBackup ''
|
||||
rm ${filesFromTmpFile}
|
||||
''}
|
||||
'';
|
||||
@@ -446,7 +497,7 @@ in
|
||||
name: backup:
|
||||
lib.nameValuePair "restic-backups-${name}" {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = backup.timerConfig;
|
||||
inherit (backup) timerConfig;
|
||||
}
|
||||
) (lib.filterAttrs (_: backup: backup.timerConfig != null) config.services.restic.backups);
|
||||
|
||||
@@ -464,7 +515,7 @@ in
|
||||
${lib.pipe config.systemd.services."restic-backups-${name}".environment [
|
||||
(lib.filterAttrs (n: v: v != null && n != "PATH"))
|
||||
(lib.mapAttrs (_: v: "${v}"))
|
||||
(lib.toShellVars)
|
||||
lib.toShellVars
|
||||
]}
|
||||
PATH=${config.systemd.services."restic-backups-${name}".environment.PATH}:$PATH
|
||||
|
||||
|
||||
Reference in New Issue
Block a user