2022-05-06 09:54:54 +00:00
|
|
|
{ config, pkgs, ... }:
|
|
|
|
let
|
|
|
|
resticPrunePre = pkgs.writeScript "resticPrunePre" ''
|
|
|
|
set -ex
|
|
|
|
|
|
|
|
# Recover from an unclean shutdown
|
|
|
|
if ${pkgs.zfs}/bin/zfs list tank/backup-old; then
|
|
|
|
${pkgs.zfs}/bin/zfs list tank/backup || ${pkgs.zfs}/bin/zfs rename tank/backup-old tank/backup
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Undo a prune that has been aborted
|
|
|
|
${pkgs.zfs}/bin/zfs destroy tank/backup-prune || true
|
|
|
|
${pkgs.zfs}/bin/zfs destroy tank/backup@prune || true
|
|
|
|
${pkgs.zfs}/bin/zfs destroy tank/backup-old || true
|
|
|
|
|
|
|
|
# Wait for the restic repository to be unlocked
|
|
|
|
while [ -n "$(${pkgs.restic}/bin/restic list locks)" ]; then
|
|
|
|
sleep
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Clone the Dataset
|
|
|
|
${pkgs.zfs}/bin/zfs snapshot tank/backup@prune
|
|
|
|
${pkgs.zfs}/bin/zfs clone tank/backup@prune tank/backup-prune
|
|
|
|
chown backup:backup /backup-prune
|
|
|
|
'';
|
|
|
|
resticPrune = pkgs.writeScript "resticPrune" ''
|
|
|
|
export RESTIC_REPOSITORY="$RESTIC_REPOSITORY-prune"
|
|
|
|
${pkgs.restic} prune --no-cache --max-unused 0
|
|
|
|
'';
|
|
|
|
resticPrunePost = pkgs.writeScript "resticPrunePost" ''
|
|
|
|
set -ex
|
|
|
|
|
|
|
|
# make the original read-only
|
|
|
|
${pkgs.zfs}/bin/zfs set readonly=on tank/backup
|
|
|
|
|
|
|
|
# Copy new data over
|
|
|
|
${pkgs.restic}/bin/restic copy --no-cache --no-lock
|
|
|
|
|
|
|
|
# Promote the pruned dataset
|
|
|
|
${pkgs.zfs}/bin/zfs promote tank/backup-prune
|
|
|
|
|
|
|
|
# Change the dataset names
|
|
|
|
${pkgs.zfs}/bin/zfs rename tank/backup tank/backup-old
|
|
|
|
${pkgs.zfs}/bin/zfs rename tank/backup-prune tank/backup
|
|
|
|
|
|
|
|
# Destroy the old dataset
|
|
|
|
${pkgs.zfs}/bin/zfs destroy -r tank/backup-old
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
{
|
2022-04-24 12:11:41 +00:00
|
|
|
users.users.backup = {
|
|
|
|
description = "Backup user";
|
|
|
|
home = "/backup";
|
|
|
|
isSystemUser = true;
|
|
|
|
openssh.authorizedKeys.keys = [
|
|
|
|
|
|
|
|
];
|
2022-04-24 12:14:47 +00:00
|
|
|
group = "backup";
|
2022-04-24 12:11:41 +00:00
|
|
|
};
|
2022-04-24 12:14:47 +00:00
|
|
|
users.groups.backup = { };
|
2022-05-06 09:54:54 +00:00
|
|
|
systemd.services.restic-prune = {
|
|
|
|
enable = true;
|
|
|
|
description = "Cleaning up restic backups";
|
|
|
|
serviceConfig = {
|
|
|
|
ExecStartPre = "!${resticPrunePre}";
|
|
|
|
ExecStart = "${resticPrune}";
|
|
|
|
ExecStartPost = "!${resticPrunePost}";
|
|
|
|
|
|
|
|
User = "backup";
|
|
|
|
Group = "backup";
|
|
|
|
Type = "oneshot";
|
|
|
|
|
|
|
|
EnvironmentFile = config.sops.secrets."services/restic/env".owner;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
sops.secrets."services/restic/env".owner = "backup";
|
2022-05-06 13:53:22 +00:00
|
|
|
sops.secrets."services/restic/rclone.conf" = {
|
|
|
|
owner = "backup";
|
|
|
|
path = "/backup/.config/rclone/rclone.conf";
|
|
|
|
};
|
|
|
|
systemd.services.backup-rclone = {
|
|
|
|
enable = true;
|
|
|
|
description = "Upload backup to remote";
|
|
|
|
script = ''
|
|
|
|
${pkgs.rclone}/bin/rclone sync /backup backup:backup-darkkirb-de/backup
|
|
|
|
'';
|
|
|
|
serviceConfig = {
|
|
|
|
User = "backup";
|
|
|
|
Group = "backup";
|
|
|
|
Type = "oneshot";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
systemd.timers.backup-rclone = {
|
|
|
|
enable = true;
|
|
|
|
description = "Upload backup to remote";
|
|
|
|
requires = [ "backup-rclone.service" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
timerConfig = {
|
|
|
|
onBootSec = 300;
|
|
|
|
onUnitActiveSec = 86400;
|
|
|
|
};
|
|
|
|
};
|
2022-04-24 12:11:41 +00:00
|
|
|
}
|