nixos/services.borgbackup: remove with lib;
This commit is contained in:
parent
1f34eeb672
commit
f51cd10816
@ -1,7 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
isLocalPath = x:
|
||||
@ -11,17 +8,17 @@ let
|
||||
|
||||
mkExcludeFile = cfg:
|
||||
# Write each exclude pattern to a new line
|
||||
pkgs.writeText "excludefile" (concatMapStrings (s: s + "\n") cfg.exclude);
|
||||
pkgs.writeText "excludefile" (lib.concatMapStrings (s: s + "\n") cfg.exclude);
|
||||
|
||||
mkPatternsFile = cfg:
|
||||
# Write each pattern to a new line
|
||||
pkgs.writeText "patternsfile" (concatMapStrings (s: s + "\n") cfg.patterns);
|
||||
pkgs.writeText "patternsfile" (lib.concatMapStrings (s: s + "\n") cfg.patterns);
|
||||
|
||||
mkKeepArgs = cfg:
|
||||
# If cfg.prune.keep e.g. has a yearly attribute,
|
||||
# its content is passed on as --keep-yearly
|
||||
concatStringsSep " "
|
||||
(mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep);
|
||||
lib.concatStringsSep " "
|
||||
(lib.mapAttrsToList (x: y: "--keep-${x}=${toString y}") cfg.prune.keep);
|
||||
|
||||
mkBackupScript = name: cfg: pkgs.writeShellScript "${name}-script" (''
|
||||
set -e
|
||||
@ -44,10 +41,10 @@ let
|
||||
fi
|
||||
}
|
||||
|
||||
archiveName="${optionalString (cfg.archiveBaseName != null) (cfg.archiveBaseName + "-")}$(date ${cfg.dateFormat})"
|
||||
archiveSuffix="${optionalString cfg.appendFailedSuffix ".failed"}"
|
||||
archiveName="${lib.optionalString (cfg.archiveBaseName != null) (cfg.archiveBaseName + "-")}$(date ${cfg.dateFormat})"
|
||||
archiveSuffix="${lib.optionalString cfg.appendFailedSuffix ".failed"}"
|
||||
${cfg.preHook}
|
||||
'' + optionalString cfg.doInit ''
|
||||
'' + lib.optionalString cfg.doInit ''
|
||||
# Run borg init if the repo doesn't exist yet
|
||||
if ! borgWrapper list $extraArgs > /dev/null; then
|
||||
borgWrapper init $extraArgs \
|
||||
@ -58,24 +55,24 @@ let
|
||||
'' + ''
|
||||
(
|
||||
set -o pipefail
|
||||
${optionalString (cfg.dumpCommand != null) ''${escapeShellArg cfg.dumpCommand} | \''}
|
||||
${lib.optionalString (cfg.dumpCommand != null) ''${lib.escapeShellArg cfg.dumpCommand} | \''}
|
||||
borgWrapper create $extraArgs \
|
||||
--compression ${cfg.compression} \
|
||||
--exclude-from ${mkExcludeFile cfg} \
|
||||
--patterns-from ${mkPatternsFile cfg} \
|
||||
$extraCreateArgs \
|
||||
"::$archiveName$archiveSuffix" \
|
||||
${if cfg.paths == null then "-" else escapeShellArgs cfg.paths}
|
||||
${if cfg.paths == null then "-" else lib.escapeShellArgs cfg.paths}
|
||||
)
|
||||
'' + optionalString cfg.appendFailedSuffix ''
|
||||
'' + lib.optionalString cfg.appendFailedSuffix ''
|
||||
borgWrapper rename $extraArgs \
|
||||
"::$archiveName$archiveSuffix" "$archiveName"
|
||||
'' + ''
|
||||
${cfg.postCreate}
|
||||
'' + optionalString (cfg.prune.keep != { }) ''
|
||||
'' + lib.optionalString (cfg.prune.keep != { }) ''
|
||||
borgWrapper prune $extraArgs \
|
||||
${mkKeepArgs cfg} \
|
||||
${optionalString (cfg.prune.prefix != null) "--glob-archives ${escapeShellArg "${cfg.prune.prefix}*"}"} \
|
||||
${lib.optionalString (cfg.prune.prefix != null) "--glob-archives ${lib.escapeShellArg "${cfg.prune.prefix}*"}"} \
|
||||
$extraPruneArgs
|
||||
borgWrapper compact $extraArgs $extraCompactArgs
|
||||
${cfg.postPrune}
|
||||
@ -93,18 +90,18 @@ let
|
||||
userHome = config.users.users.${cfg.user}.home;
|
||||
backupJobName = "borgbackup-job-${name}";
|
||||
backupScript = mkBackupScript backupJobName cfg;
|
||||
in nameValuePair backupJobName {
|
||||
in lib.nameValuePair backupJobName {
|
||||
description = "BorgBackup job ${name}";
|
||||
path = [
|
||||
config.services.borgbackup.package pkgs.openssh
|
||||
];
|
||||
script = "exec " + optionalString cfg.inhibitsSleep ''\
|
||||
script = "exec " + lib.optionalString cfg.inhibitsSleep ''\
|
||||
${pkgs.systemd}/bin/systemd-inhibit \
|
||||
--who="borgbackup" \
|
||||
--what="sleep" \
|
||||
--why="Scheduled backup" \
|
||||
'' + backupScript;
|
||||
unitConfig = optionalAttrs (isLocalPath cfg.repo) {
|
||||
unitConfig = lib.optionalAttrs (isLocalPath cfg.repo) {
|
||||
RequiresMountsFor = [ cfg.repo ];
|
||||
};
|
||||
serviceConfig = {
|
||||
@ -118,7 +115,7 @@ let
|
||||
[ "${userHome}/.config/borg" "${userHome}/.cache/borg" ]
|
||||
++ cfg.readWritePaths
|
||||
# Borg needs write access to repo if it is not remote
|
||||
++ optional (isLocalPath cfg.repo) cfg.repo;
|
||||
++ lib.optional (isLocalPath cfg.repo) cfg.repo;
|
||||
PrivateTmp = cfg.privateTmp;
|
||||
};
|
||||
environment = {
|
||||
@ -128,7 +125,7 @@ let
|
||||
};
|
||||
|
||||
mkBackupTimers = name: cfg:
|
||||
nameValuePair "borgbackup-job-${name}" {
|
||||
lib.nameValuePair "borgbackup-job-${name}" {
|
||||
description = "BorgBackup job ${name} timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
@ -136,8 +133,8 @@ let
|
||||
OnCalendar = cfg.startAt;
|
||||
};
|
||||
# if remote-backup wait for network
|
||||
after = optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target";
|
||||
wants = optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target";
|
||||
after = lib.optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target";
|
||||
wants = lib.optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target";
|
||||
};
|
||||
|
||||
# utility function around makeWrapper
|
||||
@ -148,11 +145,11 @@ let
|
||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||
} (with lib; ''
|
||||
makeWrapper "${original}" "$out/bin/${name}" \
|
||||
${concatStringsSep " \\\n " (mapAttrsToList (name: value: ''--set ${name} "${value}"'') set)}
|
||||
${lib.concatStringsSep " \\\n " (lib.mapAttrsToList (name: value: ''--set ${name} "${value}"'') set)}
|
||||
'');
|
||||
|
||||
mkBorgWrapper = name: cfg: mkWrapperDrv {
|
||||
original = getExe config.services.borgbackup.package;
|
||||
original = lib.getExe config.services.borgbackup.package;
|
||||
name = "borg-job-${name}";
|
||||
set = { BORG_REPO = cfg.repo; } // (mkPassEnv cfg) // cfg.environment;
|
||||
};
|
||||
@ -167,7 +164,7 @@ let
|
||||
"${config.users.users."${cfg.user}".home}/.cache".d = settings;
|
||||
"${config.users.users."${cfg.user}".home}/.config/borg".d = settings;
|
||||
"${config.users.users."${cfg.user}".home}/.cache/borg".d = settings;
|
||||
} // optionalAttrs (isLocalPath cfg.repo && !cfg.removableDevice) {
|
||||
} // lib.optionalAttrs (isLocalPath cfg.repo && !cfg.removableDevice) {
|
||||
"${cfg.repo}".d = settings;
|
||||
});
|
||||
|
||||
@ -180,11 +177,11 @@ let
|
||||
};
|
||||
|
||||
mkRepoService = name: cfg:
|
||||
nameValuePair "borgbackup-repo-${name}" {
|
||||
lib.nameValuePair "borgbackup-repo-${name}" {
|
||||
description = "Create BorgBackup repository ${name} directory";
|
||||
script = ''
|
||||
mkdir -p ${escapeShellArg cfg.path}
|
||||
chown ${cfg.user}:${cfg.group} ${escapeShellArg cfg.path}
|
||||
mkdir -p ${lib.escapeShellArg cfg.path}
|
||||
chown ${cfg.user}:${cfg.group} ${lib.escapeShellArg cfg.path}
|
||||
'';
|
||||
serviceConfig = {
|
||||
# The service's only task is to ensure that the specified path exists
|
||||
@ -196,10 +193,10 @@ let
|
||||
mkAuthorizedKey = cfg: appendOnly: key:
|
||||
let
|
||||
# Because of the following line, clients do not need to specify an absolute repo path
|
||||
cdCommand = "cd ${escapeShellArg cfg.path}";
|
||||
cdCommand = "cd ${lib.escapeShellArg cfg.path}";
|
||||
restrictedArg = "--restrict-to-${if cfg.allowSubRepos then "path" else "repository"} .";
|
||||
appendOnlyArg = optionalString appendOnly "--append-only";
|
||||
quotaArg = optionalString (cfg.quota != null) "--storage-quota ${cfg.quota}";
|
||||
appendOnlyArg = lib.optionalString appendOnly "--append-only";
|
||||
quotaArg = lib.optionalString (cfg.quota != null) "--storage-quota ${cfg.quota}";
|
||||
serveCommand = "borg serve ${restrictedArg} ${appendOnlyArg} ${quotaArg}";
|
||||
in
|
||||
''command="${cdCommand} && ${serveCommand}",restrict ${key}'';
|
||||
@ -224,7 +221,7 @@ let
|
||||
};
|
||||
|
||||
mkSourceAssertions = name: cfg: {
|
||||
assertion = count isNull [ cfg.dumpCommand cfg.paths ] == 1;
|
||||
assertion = lib.count isNull [ cfg.dumpCommand cfg.paths ] == 1;
|
||||
message = ''
|
||||
Exactly one of borgbackup.jobs.${name}.paths or borgbackup.jobs.${name}.dumpCommand
|
||||
must be set.
|
||||
@ -239,14 +236,14 @@ let
|
||||
};
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ dotlambda ];
|
||||
meta.maintainers = with lib.maintainers; [ dotlambda ];
|
||||
meta.doc = ./borgbackup.md;
|
||||
|
||||
###### interface
|
||||
|
||||
options.services.borgbackup.package = mkPackageOption pkgs "borgbackup" { };
|
||||
options.services.borgbackup.package = lib.mkPackageOption pkgs "borgbackup" { };
|
||||
|
||||
options.services.borgbackup.jobs = mkOption {
|
||||
options.services.borgbackup.jobs = lib.mkOption {
|
||||
description = ''
|
||||
Deduplicating backups using BorgBackup.
|
||||
Adding a job will cause a borg-job-NAME wrapper to be added
|
||||
@ -254,7 +251,7 @@ in {
|
||||
See also the chapter about BorgBackup in the NixOS manual.
|
||||
'';
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{ # for a local backup
|
||||
rootBackup = {
|
||||
paths = "/";
|
||||
@ -286,12 +283,12 @@ in {
|
||||
startAt = "daily";
|
||||
};
|
||||
'';
|
||||
type = types.attrsOf (types.submodule (let globalConfig = config; in
|
||||
type = lib.types.attrsOf (lib.types.submodule (let globalConfig = config; in
|
||||
{ name, config, ... }: {
|
||||
options = {
|
||||
|
||||
paths = mkOption {
|
||||
type = with types; nullOr (coercedTo str lib.singleton (listOf str));
|
||||
paths = lib.mkOption {
|
||||
type = with lib.types; nullOr (coercedTo str lib.singleton (listOf str));
|
||||
default = null;
|
||||
description = ''
|
||||
Path(s) to back up.
|
||||
@ -300,8 +297,8 @@ in {
|
||||
example = "/home/user";
|
||||
};
|
||||
|
||||
dumpCommand = mkOption {
|
||||
type = with types; nullOr path;
|
||||
dumpCommand = lib.mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
description = ''
|
||||
Backup the stdout of this program instead of filesystem paths.
|
||||
@ -310,22 +307,22 @@ in {
|
||||
example = "/path/to/createZFSsend.sh";
|
||||
};
|
||||
|
||||
repo = mkOption {
|
||||
type = types.str;
|
||||
repo = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Remote or local repository to back up to.";
|
||||
example = "user@machine:/path/to/repo";
|
||||
};
|
||||
|
||||
removableDevice = mkOption {
|
||||
type = types.bool;
|
||||
removableDevice = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether the repo (which must be local) is a removable device.";
|
||||
};
|
||||
|
||||
archiveBaseName = mkOption {
|
||||
type = types.nullOr (types.strMatching "[^/{}]+");
|
||||
archiveBaseName = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.strMatching "[^/{}]+");
|
||||
default = "${globalConfig.networking.hostName}-${name}";
|
||||
defaultText = literalExpression ''"''${config.networking.hostName}-<name>"'';
|
||||
defaultText = lib.literalExpression ''"''${config.networking.hostName}-<name>"'';
|
||||
description = ''
|
||||
How to name the created archives. A timestamp, whose format is
|
||||
determined by {option}`dateFormat`, will be appended. The full
|
||||
@ -335,8 +332,8 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
dateFormat = mkOption {
|
||||
type = types.str;
|
||||
dateFormat = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Arguments passed to {command}`date`
|
||||
to create a timestamp suffix for the archive name.
|
||||
@ -345,8 +342,8 @@ in {
|
||||
example = "-u +%s";
|
||||
};
|
||||
|
||||
startAt = mkOption {
|
||||
type = with types; either str (listOf str);
|
||||
startAt = lib.mkOption {
|
||||
type = with lib.types; either str (listOf str);
|
||||
default = "daily";
|
||||
description = ''
|
||||
When or how often the backup should run.
|
||||
@ -359,9 +356,9 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
persistentTimer = mkOption {
|
||||
persistentTimer = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Set the `Persistent` option for the
|
||||
@ -371,17 +368,17 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
inhibitsSleep = mkOption {
|
||||
inhibitsSleep = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Prevents the system from sleeping while backing up.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The user {command}`borg` is run as.
|
||||
User or group need read permission
|
||||
@ -390,8 +387,8 @@ in {
|
||||
default = "root";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The group borg is run as. User or group needs read permission
|
||||
for the specified {option}`paths`.
|
||||
@ -399,8 +396,8 @@ in {
|
||||
default = "root";
|
||||
};
|
||||
|
||||
encryption.mode = mkOption {
|
||||
type = types.enum [
|
||||
encryption.mode = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"repokey" "keyfile"
|
||||
"repokey-blake2" "keyfile-blake2"
|
||||
"authenticated" "authenticated-blake2"
|
||||
@ -415,8 +412,8 @@ in {
|
||||
example = "repokey-blake2";
|
||||
};
|
||||
|
||||
encryption.passCommand = mkOption {
|
||||
type = with types; nullOr str;
|
||||
encryption.passCommand = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
description = ''
|
||||
A command which prints the passphrase to stdout.
|
||||
Mutually exclusive with {option}`passphrase`.
|
||||
@ -425,8 +422,8 @@ in {
|
||||
example = "cat /path/to/passphrase_file";
|
||||
};
|
||||
|
||||
encryption.passphrase = mkOption {
|
||||
type = with types; nullOr str;
|
||||
encryption.passphrase = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
description = ''
|
||||
The passphrase the backups are encrypted with.
|
||||
Mutually exclusive with {option}`passCommand`.
|
||||
@ -436,11 +433,11 @@ in {
|
||||
default = null;
|
||||
};
|
||||
|
||||
compression = mkOption {
|
||||
compression = lib.mkOption {
|
||||
# "auto" is optional,
|
||||
# compression mode must be given,
|
||||
# compression level is optional
|
||||
type = types.strMatching "none|(auto,)?(lz4|zstd|zlib|lzma)(,[[:digit:]]{1,2})?";
|
||||
type = lib.types.strMatching "none|(auto,)?(lz4|zstd|zlib|lzma)(,[[:digit:]]{1,2})?";
|
||||
description = ''
|
||||
Compression method to use. Refer to
|
||||
{command}`borg help compression`
|
||||
@ -450,8 +447,8 @@ in {
|
||||
example = "auto,lzma";
|
||||
};
|
||||
|
||||
exclude = mkOption {
|
||||
type = with types; listOf str;
|
||||
exclude = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
description = ''
|
||||
Exclude paths matching any of the given patterns. See
|
||||
{command}`borg help patterns` for pattern syntax.
|
||||
@ -463,8 +460,8 @@ in {
|
||||
];
|
||||
};
|
||||
|
||||
patterns = mkOption {
|
||||
type = with types; listOf str;
|
||||
patterns = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
description = ''
|
||||
Include/exclude paths matching the given patterns. The first
|
||||
matching patterns is used, so if an include pattern (prefix `+`)
|
||||
@ -478,8 +475,8 @@ in {
|
||||
];
|
||||
};
|
||||
|
||||
readWritePaths = mkOption {
|
||||
type = with types; listOf path;
|
||||
readWritePaths = lib.mkOption {
|
||||
type = with lib.types; listOf path;
|
||||
description = ''
|
||||
By default, borg cannot write anywhere on the system but
|
||||
`$HOME/.config/borg` and `$HOME/.cache/borg`.
|
||||
@ -492,8 +489,8 @@ in {
|
||||
];
|
||||
};
|
||||
|
||||
privateTmp = mkOption {
|
||||
type = types.bool;
|
||||
privateTmp = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Set the `PrivateTmp` option for
|
||||
the systemd-service. Set to false if you need sockets
|
||||
@ -502,8 +499,8 @@ in {
|
||||
default = true;
|
||||
};
|
||||
|
||||
failOnWarnings = mkOption {
|
||||
type = types.bool;
|
||||
failOnWarnings = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Fail the whole backup job if any borg command returns a warning
|
||||
(exit code 1), for example because a file changed during backup.
|
||||
@ -511,8 +508,8 @@ in {
|
||||
default = true;
|
||||
};
|
||||
|
||||
doInit = mkOption {
|
||||
type = types.bool;
|
||||
doInit = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Run {command}`borg init` if the
|
||||
specified {option}`repo` does not exist.
|
||||
@ -523,8 +520,8 @@ in {
|
||||
default = true;
|
||||
};
|
||||
|
||||
appendFailedSuffix = mkOption {
|
||||
type = types.bool;
|
||||
appendFailedSuffix = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Append a `.failed` suffix
|
||||
to the archive name, which is only removed if
|
||||
@ -533,18 +530,18 @@ in {
|
||||
default = true;
|
||||
};
|
||||
|
||||
prune.keep = mkOption {
|
||||
prune.keep = lib.mkOption {
|
||||
# Specifying e.g. `prune.keep.yearly = -1`
|
||||
# means there is no limit of yearly archives to keep
|
||||
# The regex is for use with e.g. --keep-within 1y
|
||||
type = with types; attrsOf (either int (strMatching "[[:digit:]]+[Hdwmy]"));
|
||||
type = with lib.types; attrsOf (either int (strMatching "[[:digit:]]+[Hdwmy]"));
|
||||
description = ''
|
||||
Prune a repository by deleting all archives not matching any of the
|
||||
specified retention options. See {command}`borg help prune`
|
||||
for the available options.
|
||||
'';
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
within = "1d"; # Keep all archives from the last day
|
||||
daily = 7;
|
||||
@ -554,19 +551,19 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
prune.prefix = mkOption {
|
||||
type = types.nullOr (types.str);
|
||||
prune.prefix = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.str);
|
||||
description = ''
|
||||
Only consider archive names starting with this prefix for pruning.
|
||||
By default, only archives created by this job are considered.
|
||||
Use `""` or `null` to consider all archives.
|
||||
'';
|
||||
default = config.archiveBaseName;
|
||||
defaultText = literalExpression "archiveBaseName";
|
||||
defaultText = lib.literalExpression "archiveBaseName";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
environment = lib.mkOption {
|
||||
type = with lib.types; attrsOf str;
|
||||
description = ''
|
||||
Environment variables passed to the backup script.
|
||||
You can for example specify which SSH key to use.
|
||||
@ -575,8 +572,8 @@ in {
|
||||
example = { BORG_RSH = "ssh -i /path/to/key"; };
|
||||
};
|
||||
|
||||
preHook = mkOption {
|
||||
type = types.lines;
|
||||
preHook = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Shell commands to run before the backup.
|
||||
This can for example be used to mount file systems.
|
||||
@ -588,16 +585,16 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
postInit = mkOption {
|
||||
type = types.lines;
|
||||
postInit = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Shell commands to run after {command}`borg init`.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
postCreate = mkOption {
|
||||
type = types.lines;
|
||||
postCreate = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Shell commands to run after {command}`borg create`. The name
|
||||
of the created archive is stored in `$archiveName`.
|
||||
@ -605,16 +602,16 @@ in {
|
||||
default = "";
|
||||
};
|
||||
|
||||
postPrune = mkOption {
|
||||
type = types.lines;
|
||||
postPrune = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Shell commands to run after {command}`borg prune`.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
postHook = mkOption {
|
||||
type = types.lines;
|
||||
postHook = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Shell commands to run just before exit. They are executed
|
||||
even if a previous command exits with a non-zero exit code.
|
||||
@ -623,8 +620,8 @@ in {
|
||||
default = "";
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = with types; coercedTo (listOf str) escapeShellArgs str;
|
||||
extraArgs = lib.mkOption {
|
||||
type = with lib.types; coercedTo (listOf str) lib.escapeShellArgs str;
|
||||
description = ''
|
||||
Additional arguments for all {command}`borg` calls the
|
||||
service has. Handle with care.
|
||||
@ -633,8 +630,8 @@ in {
|
||||
example = [ "--remote-path=/path/to/borg" ];
|
||||
};
|
||||
|
||||
extraInitArgs = mkOption {
|
||||
type = with types; coercedTo (listOf str) escapeShellArgs str;
|
||||
extraInitArgs = lib.mkOption {
|
||||
type = with lib.types; coercedTo (listOf str) lib.escapeShellArgs str;
|
||||
description = ''
|
||||
Additional arguments for {command}`borg init`.
|
||||
Can also be set at runtime using `$extraInitArgs`.
|
||||
@ -643,8 +640,8 @@ in {
|
||||
example = [ "--append-only" ];
|
||||
};
|
||||
|
||||
extraCreateArgs = mkOption {
|
||||
type = with types; coercedTo (listOf str) escapeShellArgs str;
|
||||
extraCreateArgs = lib.mkOption {
|
||||
type = with lib.types; coercedTo (listOf str) lib.escapeShellArgs str;
|
||||
description = ''
|
||||
Additional arguments for {command}`borg create`.
|
||||
Can also be set at runtime using `$extraCreateArgs`.
|
||||
@ -656,8 +653,8 @@ in {
|
||||
];
|
||||
};
|
||||
|
||||
extraPruneArgs = mkOption {
|
||||
type = with types; coercedTo (listOf str) escapeShellArgs str;
|
||||
extraPruneArgs = lib.mkOption {
|
||||
type = with lib.types; coercedTo (listOf str) lib.escapeShellArgs str;
|
||||
description = ''
|
||||
Additional arguments for {command}`borg prune`.
|
||||
Can also be set at runtime using `$extraPruneArgs`.
|
||||
@ -666,8 +663,8 @@ in {
|
||||
example = [ "--save-space" ];
|
||||
};
|
||||
|
||||
extraCompactArgs = mkOption {
|
||||
type = with types; coercedTo (listOf str) escapeShellArgs str;
|
||||
extraCompactArgs = lib.mkOption {
|
||||
type = with lib.types; coercedTo (listOf str) lib.escapeShellArgs str;
|
||||
description = ''
|
||||
Additional arguments for {command}`borg compact`.
|
||||
Can also be set at runtime using `$extraCompactArgs`.
|
||||
@ -680,7 +677,7 @@ in {
|
||||
));
|
||||
};
|
||||
|
||||
options.services.borgbackup.repos = mkOption {
|
||||
options.services.borgbackup.repos = lib.mkOption {
|
||||
description = ''
|
||||
Serve BorgBackup repositories to given public SSH keys,
|
||||
restricting their access to the repository only.
|
||||
@ -689,11 +686,11 @@ in {
|
||||
i.e. `user@machine:.` is enough. (Note colon and dot.)
|
||||
'';
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule (
|
||||
type = lib.types.attrsOf (lib.types.submodule (
|
||||
{ ... }: {
|
||||
options = {
|
||||
path = mkOption {
|
||||
type = types.path;
|
||||
path = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
Where to store the backups. Note that the directory
|
||||
is created automatically, with correct permissions.
|
||||
@ -701,8 +698,8 @@ in {
|
||||
default = "/var/lib/borgbackup";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The user {command}`borg serve` is run as.
|
||||
User or group needs write permission
|
||||
@ -711,8 +708,8 @@ in {
|
||||
default = "borg";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The group {command}`borg serve` is run as.
|
||||
User or group needs write permission
|
||||
@ -721,8 +718,8 @@ in {
|
||||
default = "borg";
|
||||
};
|
||||
|
||||
authorizedKeys = mkOption {
|
||||
type = with types; listOf str;
|
||||
authorizedKeys = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
description = ''
|
||||
Public SSH keys that are given full write access to this repository.
|
||||
You should use a different SSH key for each repository you write to, because
|
||||
@ -732,8 +729,8 @@ in {
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
authorizedKeysAppendOnly = mkOption {
|
||||
type = with types; listOf str;
|
||||
authorizedKeysAppendOnly = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
description = ''
|
||||
Public SSH keys that can only be used to append new data (archives) to the repository.
|
||||
Note that archives can still be marked as deleted and are subsequently removed from disk
|
||||
@ -742,8 +739,8 @@ in {
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
allowSubRepos = mkOption {
|
||||
type = types.bool;
|
||||
allowSubRepos = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Allow clients to create repositories in subdirectories of the
|
||||
specified {option}`path`. These can be accessed using
|
||||
@ -755,9 +752,9 @@ in {
|
||||
default = false;
|
||||
};
|
||||
|
||||
quota = mkOption {
|
||||
quota = lib.mkOption {
|
||||
# See the definition of parse_file_size() in src/borg/helpers/parseformat.py
|
||||
type = with types; nullOr (strMatching "[[:digit:].]+[KMGTP]?");
|
||||
type = with lib.types; nullOr (strMatching "[[:digit:].]+[KMGTP]?");
|
||||
description = ''
|
||||
Storage quota for the repository. This quota is ensured for all
|
||||
sub-repositories if {option}`allowSubRepos` is enabled
|
||||
@ -774,29 +771,29 @@ in {
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf (with config.services.borgbackup; jobs != { } || repos != { })
|
||||
config = lib.mkIf (with config.services.borgbackup; jobs != { } || repos != { })
|
||||
(with config.services.borgbackup; {
|
||||
assertions =
|
||||
mapAttrsToList mkPassAssertion jobs
|
||||
++ mapAttrsToList mkKeysAssertion repos
|
||||
++ mapAttrsToList mkSourceAssertions jobs
|
||||
++ mapAttrsToList mkRemovableDeviceAssertions jobs;
|
||||
lib.mapAttrsToList mkPassAssertion jobs
|
||||
++ lib.mapAttrsToList mkKeysAssertion repos
|
||||
++ lib.mapAttrsToList mkSourceAssertions jobs
|
||||
++ lib.mapAttrsToList mkRemovableDeviceAssertions jobs;
|
||||
|
||||
systemd.tmpfiles.settings = mapAttrs' mkTmpfiles jobs;
|
||||
systemd.tmpfiles.settings = lib.mapAttrs' mkTmpfiles jobs;
|
||||
|
||||
systemd.services =
|
||||
# A job named "foo" is mapped to systemd.services.borgbackup-job-foo
|
||||
mapAttrs' mkBackupService jobs
|
||||
lib.mapAttrs' mkBackupService jobs
|
||||
# A repo named "foo" is mapped to systemd.services.borgbackup-repo-foo
|
||||
// mapAttrs' mkRepoService repos;
|
||||
// lib.mapAttrs' mkRepoService repos;
|
||||
|
||||
# A job named "foo" is mapped to systemd.timers.borgbackup-job-foo
|
||||
# only generate the timer if interval (startAt) is set
|
||||
systemd.timers = mapAttrs' mkBackupTimers (filterAttrs (_: cfg: cfg.startAt != []) jobs);
|
||||
systemd.timers = lib.mapAttrs' mkBackupTimers (lib.filterAttrs (_: cfg: cfg.startAt != []) jobs);
|
||||
|
||||
users = mkMerge (mapAttrsToList mkUsersConfig repos);
|
||||
users = lib.mkMerge (lib.mapAttrsToList mkUsersConfig repos);
|
||||
|
||||
environment.systemPackages =
|
||||
[ config.services.borgbackup.package ] ++ (mapAttrsToList mkBorgWrapper jobs);
|
||||
[ config.services.borgbackup.package ] ++ (lib.mapAttrsToList mkBorgWrapper jobs);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user