mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-09-23 05:37:27 +03:00
Merge pull request #204386 from robryk/resticassert
nixos/restic: small enhancements
This commit is contained in:
commit
99f9998309
@ -126,6 +126,21 @@ in
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exclude = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Patterns to exclude when backing up. See
|
||||||
|
https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files for
|
||||||
|
details on syntax.
|
||||||
|
'';
|
||||||
|
example = [
|
||||||
|
"/var/cache"
|
||||||
|
"/home/*/.cache"
|
||||||
|
".git"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
timerConfig = mkOption {
|
timerConfig = mkOption {
|
||||||
type = types.attrsOf unitOption;
|
type = types.attrsOf unitOption;
|
||||||
default = {
|
default = {
|
||||||
@ -249,6 +264,7 @@ in
|
|||||||
example = {
|
example = {
|
||||||
localbackup = {
|
localbackup = {
|
||||||
paths = [ "/home" ];
|
paths = [ "/home" ];
|
||||||
|
exclude = [ "/home/*/.cache" ];
|
||||||
repository = "/mnt/backup-hdd";
|
repository = "/mnt/backup-hdd";
|
||||||
passwordFile = "/etc/nixos/secrets/restic-password";
|
passwordFile = "/etc/nixos/secrets/restic-password";
|
||||||
initialize = true;
|
initialize = true;
|
||||||
@ -270,12 +286,17 @@ in
|
|||||||
|
|
||||||
config = {
|
config = {
|
||||||
warnings = mapAttrsToList (n: v: "services.restic.backups.${n}.s3CredentialsFile is deprecated, please use services.restic.backups.${n}.environmentFile instead.") (filterAttrs (n: v: v.s3CredentialsFile != null) config.services.restic.backups);
|
warnings = mapAttrsToList (n: v: "services.restic.backups.${n}.s3CredentialsFile is deprecated, please use services.restic.backups.${n}.environmentFile instead.") (filterAttrs (n: v: v.s3CredentialsFile != null) config.services.restic.backups);
|
||||||
|
assertions = 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;
|
||||||
systemd.services =
|
systemd.services =
|
||||||
mapAttrs'
|
mapAttrs'
|
||||||
(name: backup:
|
(name: backup:
|
||||||
let
|
let
|
||||||
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
|
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
|
||||||
resticCmd = "${backup.package}/bin/restic${extraOptions}";
|
resticCmd = "${backup.package}/bin/restic${extraOptions}";
|
||||||
|
excludeFlags = if (backup.exclude != []) then ["--exclude-file=${pkgs.writeText "exclude-patterns" (concatStringsSep "\n" backup.exclude)}"] else [];
|
||||||
filesFromTmpFile = "/run/restic-backups-${name}/includes";
|
filesFromTmpFile = "/run/restic-backups-${name}/includes";
|
||||||
backupPaths =
|
backupPaths =
|
||||||
if (backup.dynamicFilesFrom == null)
|
if (backup.dynamicFilesFrom == null)
|
||||||
@ -311,7 +332,7 @@ in
|
|||||||
restartIfChanged = false;
|
restartIfChanged = false;
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ])
|
ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " (backup.extraBackupArgs ++ excludeFlags)} ${backupPaths}" ])
|
||||||
++ pruneCmd;
|
++ pruneCmd;
|
||||||
User = backup.user;
|
User = backup.user;
|
||||||
RuntimeDirectory = "restic-backups-${name}";
|
RuntimeDirectory = "restic-backups-${name}";
|
||||||
|
@ -7,17 +7,27 @@ import ./make-test-python.nix (
|
|||||||
rcloneRepository = "rclone:local:/tmp/restic-rclone-backup";
|
rcloneRepository = "rclone:local:/tmp/restic-rclone-backup";
|
||||||
|
|
||||||
backupPrepareCommand = ''
|
backupPrepareCommand = ''
|
||||||
touch /opt/backupPrepareCommand
|
touch /tmp/backupPrepareCommand
|
||||||
test ! -e /opt/backupCleanupCommand
|
test ! -e /tmp/backupCleanupCommand
|
||||||
'';
|
'';
|
||||||
|
|
||||||
backupCleanupCommand = ''
|
backupCleanupCommand = ''
|
||||||
rm /opt/backupPrepareCommand
|
rm /tmp/backupPrepareCommand
|
||||||
touch /opt/backupCleanupCommand
|
touch /tmp/backupCleanupCommand
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
testDir = pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
name = "test-files-to-backup";
|
||||||
|
unpackPhase = "true";
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
touch $out/some_file
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
|
passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
|
||||||
paths = [ "/opt" ];
|
paths = [ "/opt" ];
|
||||||
|
exclude = [ "/opt/excluded_file_*" ];
|
||||||
pruneOpts = [
|
pruneOpts = [
|
||||||
"--keep-daily 2"
|
"--keep-daily 2"
|
||||||
"--keep-weekly 1"
|
"--keep-weekly 1"
|
||||||
@ -38,17 +48,17 @@ import ./make-test-python.nix (
|
|||||||
{
|
{
|
||||||
services.restic.backups = {
|
services.restic.backups = {
|
||||||
remotebackup = {
|
remotebackup = {
|
||||||
inherit passwordFile paths pruneOpts backupPrepareCommand backupCleanupCommand;
|
inherit passwordFile paths exclude pruneOpts backupPrepareCommand backupCleanupCommand;
|
||||||
repository = remoteRepository;
|
repository = remoteRepository;
|
||||||
initialize = true;
|
initialize = true;
|
||||||
};
|
};
|
||||||
remote-from-file-backup = {
|
remote-from-file-backup = {
|
||||||
inherit passwordFile paths pruneOpts;
|
inherit passwordFile paths exclude pruneOpts;
|
||||||
initialize = true;
|
initialize = true;
|
||||||
repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository;
|
repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository;
|
||||||
};
|
};
|
||||||
rclonebackup = {
|
rclonebackup = {
|
||||||
inherit passwordFile paths pruneOpts;
|
inherit passwordFile paths exclude pruneOpts;
|
||||||
initialize = true;
|
initialize = true;
|
||||||
repository = rcloneRepository;
|
repository = rcloneRepository;
|
||||||
rcloneConfig = {
|
rcloneConfig = {
|
||||||
@ -94,16 +104,21 @@ import ./make-test-python.nix (
|
|||||||
)
|
)
|
||||||
server.succeed(
|
server.succeed(
|
||||||
# set up
|
# set up
|
||||||
"mkdir -p /opt",
|
"cp -rT ${testDir} /opt",
|
||||||
"touch /opt/some_file",
|
"touch /opt/excluded_file_1 /opt/excluded_file_2",
|
||||||
"mkdir -p /tmp/restic-rclone-backup",
|
"mkdir -p /tmp/restic-rclone-backup",
|
||||||
|
|
||||||
# test that remotebackup runs custom commands and produces a snapshot
|
# test that remotebackup runs custom commands and produces a snapshot
|
||||||
"timedatectl set-time '2016-12-13 13:45'",
|
"timedatectl set-time '2016-12-13 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
'${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
|
'${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
|
||||||
|
|
||||||
|
# test that restoring that snapshot produces the same directory
|
||||||
|
"mkdir /tmp/restore-1",
|
||||||
|
"${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} restore latest -t /tmp/restore-1",
|
||||||
|
"diff -ru ${testDir} /tmp/restore-1/opt",
|
||||||
|
|
||||||
# test that remote-from-file-backup produces a snapshot
|
# test that remote-from-file-backup produces a snapshot
|
||||||
"systemctl start restic-backups-remote-from-file-backup.service",
|
"systemctl start restic-backups-remote-from-file-backup.service",
|
||||||
'${pkgs.restic}/bin/restic -r ${remoteFromFileRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
|
'${pkgs.restic}/bin/restic -r ${remoteFromFileRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
|
||||||
@ -120,27 +135,27 @@ import ./make-test-python.nix (
|
|||||||
# test that we can create four snapshots in remotebackup and rclonebackup
|
# test that we can create four snapshots in remotebackup and rclonebackup
|
||||||
"timedatectl set-time '2017-12-13 13:45'",
|
"timedatectl set-time '2017-12-13 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
"systemctl start restic-backups-rclonebackup.service",
|
"systemctl start restic-backups-rclonebackup.service",
|
||||||
|
|
||||||
"timedatectl set-time '2018-12-13 13:45'",
|
"timedatectl set-time '2018-12-13 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
"systemctl start restic-backups-rclonebackup.service",
|
"systemctl start restic-backups-rclonebackup.service",
|
||||||
|
|
||||||
"timedatectl set-time '2018-12-14 13:45'",
|
"timedatectl set-time '2018-12-14 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
"systemctl start restic-backups-rclonebackup.service",
|
"systemctl start restic-backups-rclonebackup.service",
|
||||||
|
|
||||||
"timedatectl set-time '2018-12-15 13:45'",
|
"timedatectl set-time '2018-12-15 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
"systemctl start restic-backups-rclonebackup.service",
|
"systemctl start restic-backups-rclonebackup.service",
|
||||||
|
|
||||||
"timedatectl set-time '2018-12-16 13:45'",
|
"timedatectl set-time '2018-12-16 13:45'",
|
||||||
"systemctl start restic-backups-remotebackup.service",
|
"systemctl start restic-backups-remotebackup.service",
|
||||||
"rm /opt/backupCleanupCommand",
|
"rm /tmp/backupCleanupCommand",
|
||||||
"systemctl start restic-backups-rclonebackup.service",
|
"systemctl start restic-backups-rclonebackup.service",
|
||||||
|
|
||||||
'${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
|
'${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
|
||||||
|
Loading…
Reference in New Issue
Block a user