mirror of
https://github.com/nix-community/home-manager
synced 2025-01-11 03:29:50 +01:00
borgmatic: add module
This commit is contained in:
parent
da3b8049fd
commit
04f5399978
12 changed files with 473 additions and 0 deletions
5
.github/CODEOWNERS
vendored
5
.github/CODEOWNERS
vendored
|
@ -343,6 +343,11 @@ Makefile @thiagokokada
|
||||||
|
|
||||||
/modules/services/betterlockscreen.nix @SebTM
|
/modules/services/betterlockscreen.nix @SebTM
|
||||||
|
|
||||||
|
/modules/programs/borgmatic.nix @DamienCassou
|
||||||
|
/modules/services/borgmatic.nix @DamienCassou
|
||||||
|
/tests/modules/programs/borgmatic @DamienCassou
|
||||||
|
/tests/modules/services/borgmatic @DamienCassou
|
||||||
|
|
||||||
/modules/services/caffeine.nix @uvNikita
|
/modules/services/caffeine.nix @uvNikita
|
||||||
|
|
||||||
/modules/services/cbatticon.nix @pmiddend
|
/modules/services/cbatticon.nix @pmiddend
|
||||||
|
|
|
@ -748,6 +748,20 @@ in
|
||||||
A new module is available: 'programs.discocss'.
|
A new module is available: 'programs.discocss'.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time = "2022-10-16T19:49:46+00:00";
|
||||||
|
condition = hostPlatform.isLinux;
|
||||||
|
message = ''
|
||||||
|
Two new modules are available:
|
||||||
|
|
||||||
|
- 'programs.borgmatic' and
|
||||||
|
- 'services.borgmatic'.
|
||||||
|
|
||||||
|
use the first to configure the borgmatic tool and the second if you
|
||||||
|
want to automatically run scheduled backups.
|
||||||
|
'';
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ let
|
||||||
./programs/bashmount.nix
|
./programs/bashmount.nix
|
||||||
./programs/bat.nix
|
./programs/bat.nix
|
||||||
./programs/beets.nix
|
./programs/beets.nix
|
||||||
|
./programs/borgmatic.nix
|
||||||
./programs/bottom.nix
|
./programs/bottom.nix
|
||||||
./programs/broot.nix
|
./programs/broot.nix
|
||||||
./programs/browserpass.nix
|
./programs/browserpass.nix
|
||||||
|
@ -197,6 +198,7 @@ let
|
||||||
./services/barrier.nix
|
./services/barrier.nix
|
||||||
./services/betterlockscreen.nix
|
./services/betterlockscreen.nix
|
||||||
./services/blueman-applet.nix
|
./services/blueman-applet.nix
|
||||||
|
./services/borgmatic.nix
|
||||||
./services/caffeine.nix
|
./services/caffeine.nix
|
||||||
./services/cbatticon.nix
|
./services/cbatticon.nix
|
||||||
./services/clipmenu.nix
|
./services/clipmenu.nix
|
||||||
|
|
196
modules/programs/borgmatic.nix
Normal file
196
modules/programs/borgmatic.nix
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.borgmatic;
|
||||||
|
|
||||||
|
mkNullableOption = args:
|
||||||
|
lib.mkOption (args // {
|
||||||
|
type = lib.types.nullOr args.type;
|
||||||
|
default = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
mkRetentionOption = frequency:
|
||||||
|
mkNullableOption {
|
||||||
|
type = types.int;
|
||||||
|
description =
|
||||||
|
"Number of ${frequency} archives to keep. Use -1 for no limit.";
|
||||||
|
example = 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfigOption = mkOption {
|
||||||
|
type = with types; attrsOf (oneOf [ str bool path int ]);
|
||||||
|
default = { };
|
||||||
|
description = "Extra settings.";
|
||||||
|
};
|
||||||
|
|
||||||
|
consistencyCheckModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.enum [ "repository" "archives" "data" "extract" ];
|
||||||
|
description = "Name of consistency check to run.";
|
||||||
|
example = "repository";
|
||||||
|
};
|
||||||
|
|
||||||
|
frequency = mkNullableOption {
|
||||||
|
type = types.strMatching "([[:digit:]]+ .*)|always";
|
||||||
|
description = "Frequency of this type of check";
|
||||||
|
example = "2 weeks";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
configModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
location = {
|
||||||
|
sourceDirectories = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = "Directories to backup.";
|
||||||
|
example = literalExpression "[config.home.homeDirectory]";
|
||||||
|
};
|
||||||
|
|
||||||
|
repositories = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = "Paths to repositories.";
|
||||||
|
example =
|
||||||
|
literalExpression ''["ssh://myuser@myrepo.myserver.com/./repo"]'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = extraConfigOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
storage = {
|
||||||
|
encryptionPasscommand = mkNullableOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Command writing the passphrase to standard output.";
|
||||||
|
example =
|
||||||
|
literalExpression ''"''${pkgs.password-store}/bin/pass borg-repo"'';
|
||||||
|
};
|
||||||
|
extraConfig = extraConfigOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
retention = {
|
||||||
|
keepWithin = mkNullableOption {
|
||||||
|
type = types.strMatching "[[:digit:]]+[Hdwmy]";
|
||||||
|
description = "Keep all archives within this time interval.";
|
||||||
|
example = "2d";
|
||||||
|
};
|
||||||
|
|
||||||
|
keepSecondly = mkRetentionOption "secondly";
|
||||||
|
keepMinutely = mkRetentionOption "minutely";
|
||||||
|
keepHourly = mkRetentionOption "hourly";
|
||||||
|
keepDaily = mkRetentionOption "daily";
|
||||||
|
keepWeekly = mkRetentionOption "weekly";
|
||||||
|
keepMonthly = mkRetentionOption "monthly";
|
||||||
|
keepYearly = mkRetentionOption "yearly";
|
||||||
|
|
||||||
|
extraConfig = extraConfigOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
consistency = {
|
||||||
|
checks = mkOption {
|
||||||
|
type = types.listOf consistencyCheckModule;
|
||||||
|
default = [ ];
|
||||||
|
description = "Consistency checks to run";
|
||||||
|
example = literalExpression ''
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name = "repository";
|
||||||
|
frequency = "2 weeks";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "archives";
|
||||||
|
frequency = "4 weeks";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "data";
|
||||||
|
frequency = "6 weeks";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "extract";
|
||||||
|
frequency = "6 weeks";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = extraConfigOption;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
removeNullValues = attrSet: filterAttrs (key: value: value != null) attrSet;
|
||||||
|
|
||||||
|
writeConfig = config:
|
||||||
|
generators.toYAML { } {
|
||||||
|
location = removeNullValues {
|
||||||
|
source_directories = config.location.sourceDirectories;
|
||||||
|
repositories = config.location.repositories;
|
||||||
|
} // config.location.extraConfig;
|
||||||
|
storage = removeNullValues {
|
||||||
|
encryption_passcommand = config.storage.encryptionPasscommand;
|
||||||
|
} // config.storage.extraConfig;
|
||||||
|
retention = removeNullValues {
|
||||||
|
keep_within = config.retention.keepWithin;
|
||||||
|
keep_secondly = config.retention.keepSecondly;
|
||||||
|
keep_minutely = config.retention.keepMinutely;
|
||||||
|
keep_hourly = config.retention.keepHourly;
|
||||||
|
keep_daily = config.retention.keepDaily;
|
||||||
|
keep_weekly = config.retention.keepWeekly;
|
||||||
|
keep_monthly = config.retention.keepMonthly;
|
||||||
|
keep_yearly = config.retention.keepYearly;
|
||||||
|
} // config.retention.extraConfig;
|
||||||
|
consistency = removeNullValues { checks = config.consistency.checks; }
|
||||||
|
// config.consistency.extraConfig;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
meta.maintainers = [ maintainers.DamienCassou ];
|
||||||
|
|
||||||
|
options = {
|
||||||
|
programs.borgmatic = {
|
||||||
|
enable = mkEnableOption "Borgmatic";
|
||||||
|
|
||||||
|
package = mkPackageOption pkgs "borgmatic" { };
|
||||||
|
|
||||||
|
backups = mkOption {
|
||||||
|
type = types.attrsOf configModule;
|
||||||
|
description = ''
|
||||||
|
Borgmatic allows for several named backup configurations,
|
||||||
|
each with its own source directories and repositories.
|
||||||
|
'';
|
||||||
|
example = literalExpression ''
|
||||||
|
{
|
||||||
|
personal = {
|
||||||
|
location = {
|
||||||
|
sourceDirectories = [ "/home/me/personal" ];
|
||||||
|
repositories = [ "ssh://myuser@myserver.com/./personal-repo" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
work = {
|
||||||
|
location = {
|
||||||
|
sourceDirectories = [ "/home/me/work" ];
|
||||||
|
repositories = [ "ssh://myuser@myserver.com/./work-repo" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
(lib.hm.assertions.assertPlatform "programs.borgmatic" pkgs
|
||||||
|
lib.platforms.linux)
|
||||||
|
];
|
||||||
|
|
||||||
|
xdg.configFile = with lib.attrsets;
|
||||||
|
mapAttrs' (configName: config:
|
||||||
|
nameValuePair ("borgmatic.d/" + configName + ".yaml") {
|
||||||
|
text = writeConfig config;
|
||||||
|
}) cfg.backups;
|
||||||
|
|
||||||
|
home.packages = [ cfg.package ];
|
||||||
|
};
|
||||||
|
}
|
87
modules/services/borgmatic.nix
Normal file
87
modules/services/borgmatic.nix
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
serviceConfig = config.services.borgmatic;
|
||||||
|
programConfig = config.programs.borgmatic;
|
||||||
|
in {
|
||||||
|
meta.maintainers = [ maintainers.DamienCassou ];
|
||||||
|
|
||||||
|
options = {
|
||||||
|
services.borgmatic = {
|
||||||
|
enable = mkEnableOption "Borgmatic service";
|
||||||
|
|
||||||
|
frequency = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "hourly";
|
||||||
|
description = ''
|
||||||
|
How often to run borgmatic when
|
||||||
|
<code language="nix">services.borgmatic.enable = true</code>.
|
||||||
|
This value is passed to the systemd timer configuration as
|
||||||
|
the onCalendar option. See
|
||||||
|
<citerefentry>
|
||||||
|
<refentrytitle>systemd.time</refentrytitle>
|
||||||
|
<manvolnum>7</manvolnum>
|
||||||
|
</citerefentry>
|
||||||
|
for more information about the format.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf serviceConfig.enable {
|
||||||
|
assertions = [
|
||||||
|
(lib.hm.assertions.assertPlatform "services.borgmatic" pkgs
|
||||||
|
lib.platforms.linux)
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.user = {
|
||||||
|
services.borgmatic = {
|
||||||
|
Unit = {
|
||||||
|
Description = "borgmatic backup";
|
||||||
|
# Prevent borgmatic from running unless the machine is
|
||||||
|
# plugged into power:
|
||||||
|
ConditionACPower = true;
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
|
||||||
|
# Lower CPU and I/O priority:
|
||||||
|
Nice = 19;
|
||||||
|
CPUSchedulingPolicy = "batch";
|
||||||
|
IOSchedulingClass = "best-effort";
|
||||||
|
IOSchedulingPriority = 7;
|
||||||
|
IOWeight = 100;
|
||||||
|
|
||||||
|
Restart = "no";
|
||||||
|
LogRateLimitIntervalSec = 0;
|
||||||
|
|
||||||
|
# Delay start to prevent backups running during boot:
|
||||||
|
ExecStartPre = "sleep 3m";
|
||||||
|
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.systemd}/bin/systemd-inhibit \
|
||||||
|
--who="borgmatic" \
|
||||||
|
--why="Prevent interrupting scheduled backup" \
|
||||||
|
${programConfig.package}/bin/borgmatic \
|
||||||
|
--stats \
|
||||||
|
--verbosity -1 \
|
||||||
|
--list \
|
||||||
|
--syslog-verbosity 1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
timers.borgmatic = {
|
||||||
|
Unit.Description = "Run borgmatic backup";
|
||||||
|
Timer = {
|
||||||
|
OnCalendar = serviceConfig.frequency;
|
||||||
|
Persistent = true;
|
||||||
|
RandomizedDelaySec = "10m";
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "timers.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -141,6 +141,7 @@ import nmt {
|
||||||
./modules/misc/xsession
|
./modules/misc/xsession
|
||||||
./modules/programs/abook
|
./modules/programs/abook
|
||||||
./modules/programs/autorandr
|
./modules/programs/autorandr
|
||||||
|
./modules/programs/borgmatic
|
||||||
./modules/programs/firefox
|
./modules/programs/firefox
|
||||||
./modules/programs/foot
|
./modules/programs/foot
|
||||||
./modules/programs/getmail
|
./modules/programs/getmail
|
||||||
|
@ -160,6 +161,7 @@ import nmt {
|
||||||
./modules/programs/xmobar
|
./modules/programs/xmobar
|
||||||
./modules/programs/yt-dlp
|
./modules/programs/yt-dlp
|
||||||
./modules/services/barrier
|
./modules/services/barrier
|
||||||
|
./modules/services/borgmatic
|
||||||
./modules/services/devilspie2
|
./modules/services/devilspie2
|
||||||
./modules/services/dropbox
|
./modules/services/dropbox
|
||||||
./modules/services/emacs
|
./modules/services/emacs
|
||||||
|
|
110
tests/modules/programs/borgmatic/basic-configuration.nix
Normal file
110
tests/modules/programs/borgmatic/basic-configuration.nix
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
boolToString = bool: if bool then "true" else "false";
|
||||||
|
backups = config.programs.borgmatic.backups;
|
||||||
|
in {
|
||||||
|
config = {
|
||||||
|
programs.borgmatic = {
|
||||||
|
enable = true;
|
||||||
|
backups = {
|
||||||
|
main = {
|
||||||
|
location = {
|
||||||
|
sourceDirectories = [ "/my-stuff-to-backup" ];
|
||||||
|
repositories = [ "/mnt/disk1" "/mnt/disk2" ];
|
||||||
|
extraConfig = { one_file_system = true; };
|
||||||
|
};
|
||||||
|
|
||||||
|
storage = {
|
||||||
|
encryptionPasscommand = "fetch-the-password.sh";
|
||||||
|
extraConfig = { checkpoint_interval = 200; };
|
||||||
|
};
|
||||||
|
|
||||||
|
retention = {
|
||||||
|
keepWithin = "14d";
|
||||||
|
keepSecondly = 12;
|
||||||
|
extraConfig = { prefix = "hostname"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
consistency = {
|
||||||
|
checks = [
|
||||||
|
{
|
||||||
|
name = "repository";
|
||||||
|
frequency = "2 weeks";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "archives";
|
||||||
|
frequency = "4 weeks";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
extraConfig = { prefix = "hostname"; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
test.stubs.borgmatic = { };
|
||||||
|
|
||||||
|
nmt.script = ''
|
||||||
|
config_file=$TESTED/home-files/.config/borgmatic.d/main.yaml
|
||||||
|
assertFileExists $config_file
|
||||||
|
|
||||||
|
declare -A expectations
|
||||||
|
|
||||||
|
expectations[location.source_directories[0]]="${
|
||||||
|
builtins.elemAt backups.main.location.sourceDirectories 0
|
||||||
|
}"
|
||||||
|
expectations[location.repositories[0]]="${
|
||||||
|
builtins.elemAt backups.main.location.repositories 0
|
||||||
|
}"
|
||||||
|
expectations[location.repositories[1]]="${
|
||||||
|
builtins.elemAt backups.main.location.repositories 1
|
||||||
|
}"
|
||||||
|
expectations[location.one_file_system]="${
|
||||||
|
boolToString backups.main.location.extraConfig.one_file_system
|
||||||
|
}"
|
||||||
|
|
||||||
|
expectations[storage.encryption_passcommand]="${backups.main.storage.encryptionPasscommand}"
|
||||||
|
expectations[storage.checkpoint_interval]="${
|
||||||
|
toString backups.main.storage.extraConfig.checkpoint_interval
|
||||||
|
}"
|
||||||
|
|
||||||
|
expectations[retention.keep_within]="${backups.main.retention.keepWithin}"
|
||||||
|
expectations[retention.keep_secondly]="${
|
||||||
|
toString backups.main.retention.keepSecondly
|
||||||
|
}"
|
||||||
|
expectations[retention.prefix]="${backups.main.retention.extraConfig.prefix}"
|
||||||
|
|
||||||
|
expectations[consistency.checks[0].name]="${
|
||||||
|
(builtins.elemAt backups.main.consistency.checks 0).name
|
||||||
|
}"
|
||||||
|
expectations[consistency.checks[0].frequency]="${
|
||||||
|
(builtins.elemAt backups.main.consistency.checks 0).frequency
|
||||||
|
}"
|
||||||
|
expectations[consistency.checks[1].name]="${
|
||||||
|
(builtins.elemAt backups.main.consistency.checks 1).name
|
||||||
|
}"
|
||||||
|
expectations[consistency.checks[1].frequency]="${
|
||||||
|
(builtins.elemAt backups.main.consistency.checks 1).frequency
|
||||||
|
}"
|
||||||
|
expectations[consistency.prefix]="${backups.main.consistency.extraConfig.prefix}"
|
||||||
|
|
||||||
|
yq=${pkgs.yq-go}/bin/yq
|
||||||
|
|
||||||
|
for filter in "''${!expectations[@]}"; do
|
||||||
|
expected_value="''${expectations[$filter]}"
|
||||||
|
actual_value="$($yq ".$filter" $config_file)"
|
||||||
|
|
||||||
|
if [[ "$actual_value" != "$expected_value" ]]; then
|
||||||
|
fail "Expected '$filter' to be '$expected_value' but was '$actual_value'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
one_file_system=$($yq ".location.one_file_system" $config_file)
|
||||||
|
if [[ $one_file_system != "true" ]]; then
|
||||||
|
fail "Expected one_file_system to be true but it was $one_file_system"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
1
tests/modules/programs/borgmatic/default.nix
Normal file
1
tests/modules/programs/borgmatic/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{ borgmatic-program-basic-configuration = ./basic-configuration.nix; }
|
22
tests/modules/services/borgmatic/basic-configuration.nix
Normal file
22
tests/modules/services/borgmatic/basic-configuration.nix
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
services.borgmatic = {
|
||||||
|
enable = true;
|
||||||
|
frequency = "weekly";
|
||||||
|
};
|
||||||
|
|
||||||
|
test.stubs.borgmatic = { };
|
||||||
|
|
||||||
|
nmt.script = ''
|
||||||
|
assertFileContent \
|
||||||
|
$(normalizeStorePaths home-files/.config/systemd/user/borgmatic.service) \
|
||||||
|
${./basic-configuration.service}
|
||||||
|
|
||||||
|
assertFileContent \
|
||||||
|
home-files/.config/systemd/user/borgmatic.timer \
|
||||||
|
${./basic-configuration.timer}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
23
tests/modules/services/borgmatic/basic-configuration.service
Normal file
23
tests/modules/services/borgmatic/basic-configuration.service
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[Service]
|
||||||
|
CPUSchedulingPolicy=batch
|
||||||
|
ExecStart=/nix/store/00000000000000000000000000000000-systemd/bin/systemd-inhibit \
|
||||||
|
--who="borgmatic" \
|
||||||
|
--why="Prevent interrupting scheduled backup" \
|
||||||
|
@borgmatic@/bin/borgmatic \
|
||||||
|
--stats \
|
||||||
|
--verbosity -1 \
|
||||||
|
--list \
|
||||||
|
--syslog-verbosity 1
|
||||||
|
|
||||||
|
ExecStartPre=sleep 3m
|
||||||
|
IOSchedulingClass=best-effort
|
||||||
|
IOSchedulingPriority=7
|
||||||
|
IOWeight=100
|
||||||
|
LogRateLimitIntervalSec=0
|
||||||
|
Nice=19
|
||||||
|
Restart=no
|
||||||
|
Type=oneshot
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
ConditionACPower=true
|
||||||
|
Description=borgmatic backup
|
10
tests/modules/services/borgmatic/basic-configuration.timer
Normal file
10
tests/modules/services/borgmatic/basic-configuration.timer
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=weekly
|
||||||
|
Persistent=true
|
||||||
|
RandomizedDelaySec=10m
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Run borgmatic backup
|
1
tests/modules/services/borgmatic/default.nix
Normal file
1
tests/modules/services/borgmatic/default.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{ borgmatic-service-basic-configuration = ./basic-configuration.nix; }
|
Loading…
Reference in a new issue