Merge pull request #37897 from mkaito/tarsnap-symlinks-and-restore

Tarsnap: add symlink options and a restore service
This commit is contained in:
Yegor Timoshenko 2018-03-27 16:21:28 +00:00 committed by GitHub
commit e61d69bfd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 60 additions and 7 deletions

View File

@ -238,6 +238,20 @@ in
Whether to produce verbose logging output. Whether to produce verbose logging output.
''; '';
}; };
explicitSymlinks = mkOption {
type = types.bool;
default = false;
description = ''
Whether to follow symlinks specified as archives.
'';
};
followSymlinks = mkOption {
type = types.bool;
default = false;
description = ''
Whether to follow all symlinks in archive trees.
'';
};
}; };
} }
)); ));
@ -285,12 +299,12 @@ in
}) gcfg.archives); }) gcfg.archives);
systemd.services = systemd.services =
mapAttrs' (name: cfg: nameValuePair "tarsnap-${name}" { (mapAttrs' (name: cfg: nameValuePair "tarsnap-${name}" {
description = "Tarsnap archive '${name}'"; description = "Tarsnap archive '${name}'";
requires = [ "network-online.target" ]; requires = [ "network-online.target" ];
after = [ "network-online.target" ]; after = [ "network-online.target" ];
path = [ pkgs.iputils pkgs.tarsnap pkgs.utillinux ]; path = with pkgs; [ iputils tarsnap utillinux ];
# In order for the persistent tarsnap timer to work reliably, we have to # In order for the persistent tarsnap timer to work reliably, we have to
# make sure that the tarsnap server is reachable after systemd starts up # make sure that the tarsnap server is reachable after systemd starts up
@ -300,10 +314,12 @@ in
while ! ping -q -c 1 v1-0-0-server.tarsnap.com &> /dev/null; do sleep 3; done while ! ping -q -c 1 v1-0-0-server.tarsnap.com &> /dev/null; do sleep 3; done
''; '';
script = script = let
let run = ''tarsnap --configfile "/etc/tarsnap/${name}.conf" \ tarsnap = ''tarsnap --configfile "/etc/tarsnap/${name}.conf"'';
-c -f "${name}-$(date +"%Y%m%d%H%M%S")" \ run = ''${tarsnap} -c -f "${name}-$(date +"%Y%m%d%H%M%S")" \
${optionalString cfg.verbose "-v"} \ ${optionalString cfg.verbose "-v"} \
${optionalString cfg.explicitSymlinks "-H"} \
${optionalString cfg.followSymlinks "-L"} \
${concatStringsSep " " cfg.directories}''; ${concatStringsSep " " cfg.directories}'';
in if (cfg.cachedir != null) then '' in if (cfg.cachedir != null) then ''
mkdir -p ${cfg.cachedir} mkdir -p ${cfg.cachedir}
@ -313,7 +329,7 @@ in
if [ ! -e ${cfg.cachedir}/firstrun ]; then if [ ! -e ${cfg.cachedir}/firstrun ]; then
( flock 10 ( flock 10
flock -u 9 flock -u 9
tarsnap --configfile "/etc/tarsnap/${name}.conf" --fsck ${tarsnap} --fsck
flock 9 flock 9
) 10>${cfg.cachedir}/firstrun ) 10>${cfg.cachedir}/firstrun
fi fi
@ -329,7 +345,44 @@ in
CapabilityBoundingSet = [ "CAP_DAC_READ_SEARCH" ]; CapabilityBoundingSet = [ "CAP_DAC_READ_SEARCH" ];
PermissionsStartOnly = "true"; PermissionsStartOnly = "true";
}; };
}) gcfg.archives; }) gcfg.archives) //
(mapAttrs' (name: cfg: nameValuePair "tarsnap-restore-${name}"{
description = "Tarsnap restore '${name}'";
requires = [ "network-online.target" ];
path = with pkgs; [ iputils tarsnap utillinux ];
script = let
tarsnap = ''tarsnap --configfile "/etc/tarsnap/${name}.conf"'';
lastArchive = ''$(${tarsnap} --list-archives | sort | tail -1)'';
run = ''${tarsnap} -x -f "${lastArchive}" ${optionalString cfg.verbose "-v"}'';
in if (cfg.cachedir != null) then ''
mkdir -p ${cfg.cachedir}
chmod 0700 ${cfg.cachedir}
( flock 9
if [ ! -e ${cfg.cachedir}/firstrun ]; then
( flock 10
flock -u 9
${tarsnap} --fsck
flock 9
) 10>${cfg.cachedir}/firstrun
fi
) 9>${cfg.cachedir}/lockf
exec flock ${cfg.cachedir}/firstrun ${run}
'' else "exec ${run}";
serviceConfig = {
Type = "oneshot";
IOSchedulingClass = "idle";
NoNewPrivileges = "true";
CapabilityBoundingSet = [ "CAP_DAC_READ_SEARCH" ];
PermissionsStartOnly = "true";
};
}) gcfg.archives);
# Note: the timer must be Persistent=true, so that systemd will start it even # Note: the timer must be Persistent=true, so that systemd will start it even
# if e.g. your laptop was asleep while the latest interval occurred. # if e.g. your laptop was asleep while the latest interval occurred.