Skip to content
Permalink
7f634fb9a9
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
88 lines (83 sloc) 3.44 KB
{ pkgs, lib, config, options, ... }:
with lib;
let
dot = f: g: x: f (g x);
compose = foldr dot id;
withUser = n: v: { user = "restic-${n}"; };
cacheDir = n: "/var/tmp/restic-${n}";
withCache = n: v: { extraBackupArgs = v.extraBackupArgs ++ [ "--cache-dir ${cacheDir n}" ]; };
extendAttrs = f: mapAttrs (n: v: v // (f n v));
rename = mapAttrs' (n: v: nameValuePair "generated-${n}" v);
augmentedBackups = compose ((map extendAttrs [ withUser withCache ]) ++ [ rename ]) config.resticSeparateUser.backups;
setfacl = "${pkgs.acl.bin}/bin/setfacl";
in
{
options.resticSeparateUser.backups = mkOption {
description = ''
Periodic backups to create with Restic employing autogenerated users.
'';
type = with types; attrsOf
(submodule ({name, ...}:
mapAttrs (n: v:
if n == "options" then
filterAttrs (n: v: n != "user") v
else
v
) ((head options.services.restic.backups.type.getSubModules).submodule { name = name; })));
default = options.services.restic.backups.default;
example = options.services.restic.backups.example;
};
config = {
services.restic.backups = augmentedBackups;
environment.systemPackages = [ pkgs.restic ];
# create users
users.users = mapAttrs' (n: v: nameValuePair v.user { isSystemUser = true; }) augmentedBackups;
# create and set permissions for cache directory
system.activationScripts = mapAttrs' (n: v: nameValuePair
"restic-backups-${n}-cachedir"
{
text = ''
${pkgs.coreutils}/bin/mkdir -pm 0700 ${cacheDir n}
${pkgs.coreutils}/bin/chown ${v.user} ${cacheDir n}
${setfacl} -k ${cacheDir n}
'';
deps = [];
}) augmentedBackups;
# add permissions for paths
# necessary to do as prestart because a default set with X would make newly created files executable
# and because some applications change the ACL mask upon saving
systemd.services =
let
# make sure to run before any other setfacl calls as they are destructive
makeAccessible = entity: target: ''
current=${target}
while current="$(dirname "$current")"; do
${setfacl} --mask -m ${entity}:x "$current" || break
if [ "$current" = "/" ]; then
break
fi
done
'';
in
mapAttrs' (n: v:
nameValuePair "restic-backups-${n}" {
# deprecated in 19.09, see nixos/nixpkgs#53852
serviceConfig.PermissionsStartOnly = true;
preStart = ''
${makeAccessible "u:${v.user}" v.passwordFile}
${setfacl} --mask -m u:${v.user}:r ${v.passwordFile}
${optionalString (!(isNull v.s3CredentialsFile)) ''
${makeAccessible "u:${v.user}" v.s3CredentialsFile}
${setfacl} --mask -m u:${v.user}:r ${v.s3CredentialsFile}
''}
${setfacl} --mask -Rm u:${v.user}:rX ${concatStringsSep " " v.paths}
'';
postStart = ''
# supressing errors from the rmeoval of proc directories that races with their permissions being removed
stderr=$(${setfacl} --mask -Rx u:s${v.user} / 2>&1 >/dev/null)
status=$?
[[ $status -eq 0 ]] || ${pkgs.gnugrep}/bin/grep "No such file or directory" <<< "$stderr" || ${pkgs.coreutils}/bin/echo "$stderr" && exit $status
'';
} ) augmentedBackups;
};
}