149 lines
4.6 KiB
Nix
149 lines
4.6 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
/*
|
|
this module enables a backup script made with borg!
|
|
to use import & set the options below
|
|
to declare a backup add the following code
|
|
to a module and it will backup all listed paths
|
|
in a borg archive to the specified repo
|
|
|
|
| <3yy> |
|
|
V V
|
|
modules.system.backups.baks = {
|
|
${service} = { paths = [ cfg.data_dir ]; };
|
|
};
|
|
*/
|
|
|
|
let
|
|
cfg = config.modules.system.backups;
|
|
sec = config.sops.secrets;
|
|
borg = "${pkgs.borgbackup}/bin/borg";
|
|
in
|
|
{
|
|
options.modules.system.backups = {
|
|
enable = lib.mkEnableOption "enables backups with borg";
|
|
baks = lib.mkOption {
|
|
type = lib.types.attrsOf (lib.types.attrsOf (lib.types.listOf lib.types.path));
|
|
default = {};
|
|
description = "backup jobs, nested attribute sets should be <bak_name> = paths [<list_of_paths>]";
|
|
};
|
|
paths = lib.mkOption {
|
|
type = lib.types.list;
|
|
};
|
|
repo = lib.mkOption {
|
|
type = lib.types.path;
|
|
default = "/holocron/borg";
|
|
description = "borg repository path";
|
|
};
|
|
passwd_file = lib.mkOption {
|
|
type = lib.types.path;
|
|
default = sec."borg_passwd".path;
|
|
description = "borg repository passphrase file";
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf (cfg.enable && cfg.baks != {}) {
|
|
|
|
systemd.services.backups = {
|
|
description = "backup service with borg!";
|
|
path = [ pkgs.borgbackup ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
# EnvironmentFile = config.modules.system.backups.passphraseFile;
|
|
# the actual script borg is using
|
|
ExecStart = pkgs.writeShellScript "borg-backup" ''
|
|
set -euo pipefail
|
|
export BORG_PASSPHRASE="$(cat ${cfg.passwd_file})"
|
|
export BORG_REPO="${cfg.repo}"
|
|
timestamp="$(date +'%Y-%m-%d_%H:%M:%S')"
|
|
mode=all
|
|
|
|
# init repo in needed
|
|
if ! borg info "$BORG_REPO" >/dev/null 2>&1; then
|
|
echo "Initializing Borg repo at $BORG_REPO"
|
|
borg init --encryption=repokey "$BORG_REPO"
|
|
fi
|
|
|
|
borg break-lock "$BORG_REPO" || true
|
|
|
|
echo "starting backup at $timestamp"
|
|
|
|
if [ "$mode" = "sep" ]; then
|
|
# loop for each backup
|
|
${lib.concatStringsSep "\n\n" (lib.mapAttrsToList (bak_name: bak_paths:
|
|
''
|
|
echo "------------ Backing up ${bak_name} ------------"
|
|
archive="$timestamp-${bak_name}"
|
|
echo "backing up: ${lib.concatStringsSep " " bak_paths.paths} → $archive"
|
|
borg create \
|
|
--verbose \
|
|
--filter AME \
|
|
--list \
|
|
--stats \
|
|
--show-rc \
|
|
--compression lzma,9 \
|
|
"$BORG_REPO::$archive" \
|
|
${lib.concatStringsSep " " bak_paths.paths}
|
|
echo "pruning old backups for ${bak_name}..."
|
|
borg prune -v --list "$BORG_REPO" \
|
|
--prefix "${bak_name}-" \
|
|
--keep-daily=7 \
|
|
--keep-weekly=52 \
|
|
--keep-monthly=-1
|
|
echo "backup run complete at \"$BORG_REPO::$archive\""
|
|
exit 0
|
|
''
|
|
) cfg.baks)}
|
|
else
|
|
# flatten all paths from cfg.baks into one big list
|
|
all_paths="${
|
|
lib.concatStringsSep " "
|
|
(lib.flatten
|
|
(lib.mapAttrsToList (_: bak: bak.paths) cfg.baks))
|
|
}"
|
|
borg create \
|
|
--verbose \
|
|
--filter AME \
|
|
--list \
|
|
--stats \
|
|
--show-rc \
|
|
--compression lzma,9 \
|
|
"$BORG_REPO::$timestamp-${toString config.networking.hostName}" \
|
|
$all_paths
|
|
|
|
echo "pruning old backups for ${toString config.networking.hostName}..."
|
|
borg prune -v --list "$BORG_REPO" \
|
|
--prefix "${toString config.networking.hostName}" \
|
|
--keep-daily=7 \
|
|
--keep-weekly=52 \
|
|
--keep-monthly=-1
|
|
echo "backup run complete at \"$BORG_REPO::${toString config.networking.hostName}\""
|
|
exit 0
|
|
fi
|
|
'';
|
|
};
|
|
};
|
|
|
|
# create timer to run backups daily
|
|
systemd.timers.backups = {
|
|
description = "daily borg backup timer";
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnCalendar = "daily";
|
|
Persistent = true;
|
|
};
|
|
};
|
|
|
|
# install borg binary
|
|
environment.systemPackages = [ pkgs.borgbackup ];
|
|
|
|
# declare secret for repo password
|
|
sops.secrets = {
|
|
"borg_passwd" = {
|
|
owner = "root";
|
|
group = "root";
|
|
};
|
|
};
|
|
};
|
|
}
|