add localbackup provider

This commit is contained in:
Jörg Thalheim 2024-03-19 19:23:14 +01:00
parent 691d2ca3e9
commit f5d32d0b22
3 changed files with 155 additions and 3 deletions

View File

@ -97,12 +97,12 @@ in
list = ''
set -efu
# we need yes here to skip the changed url verification
${
lib.concatMapStringsSep "\\\n" (
(${
lib.concatMapStringsSep "\n" (
dest:
''yes y | borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.repo}::" + .name), "job_name": "${dest.name}"}]' ''
) (lib.attrValues cfg.destinations)
} | jq -s 'add'
}) | jq -s 'add'
'';
create = ''
${lib.concatMapStringsSep "\n" (dest: ''

View File

@ -8,6 +8,7 @@
];
};
borgbackup = ./borgbackup.nix;
localbackup = ./localbackup.nix;
deltachat = ./deltachat.nix;
moonlight = ./moonlight.nix;
sunshine = ./sunshine.nix;

151
clanModules/localbackup.nix Normal file
View File

@ -0,0 +1,151 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.clan.localbackup;
rsnapshotConfig = target: states: ''
config_version 1.2
snapshot_root ${target}
sync_first 1
cmd_cp ${pkgs.coreutils}/bin/cp
cmd_rm ${pkgs.coreutils}/bin/rm
cmd_rsync ${pkgs.rsync}/bin/rsync
cmd_ssh ${pkgs.openssh}/bin/ssh
cmd_logger ${pkgs.inetutils}/bin/logger
cmd_du ${pkgs.coreutils}/bin/du
cmd_rsnapshot_diff ${pkgs.rsnapshot}/bin/rsnapshot-diff
retain snapshot ${builtins.toString config.clan.localbackup.snapshots}
${lib.concatMapStringsSep "\n" (state: ''
${lib.concatMapStringsSep "\n" (folder: ''
backup ${folder} ${config.networking.hostName}/
'') state.folders}
'') states}
'';
in
{
options.clan.localbackup = {
targets = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
description = "the name of the backup job";
};
directory = lib.mkOption {
type = lib.types.str;
description = "the directory to backup";
};
mountpoint = lib.mkOption {
type = lib.types.nullOr (lib.types.strMatching "^[a-zA-Z0-9./_-]+$");
default = null;
description = "mountpoint of the directory to backup. If set, the directory will be mounted before the backup and unmounted afterwards";
};
};
}
)
);
description = "List of directories where backups are stored";
};
snapshots = lib.mkOption {
type = lib.types.int;
default = 20;
description = "Number of snapshots to keep";
};
};
config =
let
setupMount =
mountpoint:
lib.optionalString (mountpoint != null) ''
mkdir -p ${lib.escapeShellArg mountpoint}
if mountpoint -q ${lib.escapeShellArg mountpoint}; then
umount ${lib.escapeShellArg mountpoint}
fi
mount ${lib.escapeShellArg mountpoint}
trap "umount ${lib.escapeShellArg mountpoint}" EXIT
'';
in
lib.mkIf (cfg.targets != [ ]) {
environment.systemPackages = [
(pkgs.writeShellScriptBin "localbackup-create" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsnapshot
pkgs.coreutils
pkgs.util-linux
]
}
${lib.concatMapStringsSep "\n" (target: ''
(
echo "Creating backup '${target.name}'"
${setupMount target.mountpoint}
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target.directory (lib.attrValues config.clanCore.state))}" sync
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target.directory (lib.attrValues config.clanCore.state))}" snapshot
)
'') (builtins.attrValues cfg.targets)}
'')
(pkgs.writeShellScriptBin "localbackup-list" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.jq
pkgs.findutils
pkgs.coreutils
pkgs.util-linux
]
}
(${
lib.concatMapStringsSep "\n" (target: ''
(
${setupMount target.mountpoint}
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.mountpoint}::" + .)}'
)
'') (builtins.attrValues cfg.targets)
}) | jq -s .
'')
(pkgs.writeShellScriptBin "localbackup-restore" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsync
pkgs.coreutils
pkgs.util-linux
pkgs.gawk
]
}
mountpoint=$(awk -F'::' '{print $1}' <<< $NAME)
backupname=''${NAME#$mountpoint::}
mkdir -p "$mountpoint"
if mountpoint -q "$mountpoint"; then
umount "$mountpoint"
fi
mount "$mountpoint"
trap "umount $mountpoint" EXIT
IFS=';' read -ra FOLDER <<< "$FOLDERS"
for folder in "''${FOLDER[@]}"; do
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
done
'')
];
clanCore.backups.providers.localbackup = {
# TODO list needs to run locally or on the remote machine
list = "localbackup-list";
create = "localbackup-create";
restore = "localbackup-restore";
};
};
}