service/backup: modularize backup

This commit is contained in:
Felix Buehler 2022-12-04 18:06:51 +01:00
parent a0d8c5cb7c
commit 52ec14a3c1
7 changed files with 162 additions and 159 deletions

View file

@ -0,0 +1,131 @@
{ config, lib, pkgs, ... }:
let
cfg = config.my.services.backup;
borgbackupPath = "u181505-sub1@u181505-sub1.your-storagebox.de";
in
{
options.my.services.backup = with lib; {
enable = mkEnableOption "Borgbackup Service";
passwordFile = mkOption {
type = types.path;
description = "Password for the backup";
example = "/run/secrets/password";
};
sshKeyFile = mkOption {
type = types.path;
description = "ssh-key for remote access";
example = "/run/secrets/ssh_key";
};
OnFailureNotification = mkOption {
type = types.bool;
description = "whether to show a warning to all users or not";
default = false;
};
OnFailureMail = mkOption {
type = types.nullOr (types.str);
description = "Mail adress where to send the error report";
default = null;
example = "alarm@mail.com";
};
paths = mkOption {
type = with types; listOf str;
description = "additional path(s) to back up";
default = [ "/" ];
example = [
"/home/user"
];
};
exclude = mkOption {
type = with types; listOf str;
description = "Exclude paths matching any of the given patterns. See `borg help patterns`";
default = [ ];
example = [
"/home/*/.cache"
"/tmp"
];
};
};
config = lib.mkIf cfg.enable {
# mails can only be delivered if postfix is available
services.postfix.enable = cfg.OnFailureMail != null;
services.borgbackup.jobs.hetzner = {
# always backup everything and only define excludes
inherit (cfg) paths;
exclude = [
"/nix"
"/sys"
"/run"
"/proc"
"/root/.cache/"
"**/.Trash"
"/tmp"
"/var/lock"
"/var/lib/docker/devicemapper"
"/var/run"
"/var/tmp"
"/srv/data/tmp"
"/srv/data/todo"
"/home/*/.cache"
"/home/*/.gvfs"
"/home/*/.local/share/Trash"
"/home/*/.thumbnails"
"/home/*/tmp"
"/home/*/todo"
] ++ cfg.exclude;
extraCreateArgs = "--exclude-caches --keep-exclude-tags --stats";
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${cfg.passwordFile}";
};
environment.BORG_RSH = "ssh -o 'StrictHostKeyChecking=no' -i ${cfg.sshKeyFile} -p 23";
repo = borgbackupPath + ":${config.networking.hostName}/";
doInit = false;
compression = "auto,zstd";
postHook = ''
if [[ $exitStatus != 0 ]]; then
'' + lib.optionalString cfg.OnFailureNotification ''
# iterate over all logged in users
for user in $(users); do
sway_pid=$(${pkgs.procps}/bin/pgrep -x "sway" -u "$user")
if [ -n "$sway_pid" ]; then
# set environment variables
export $(cat /proc/$sway_pid/environ | grep -z '^DBUS_SESSION_BUS_ADDRESS=' | tr -d '\0')
export DISPLAY=:0
# send notification via dbus: https://wiki.archlinux.org/title/Desktop_notifications#Bash
${pkgs.sudo}/bin/sudo --preserve-env=DBUS_SESSION_BUS_ADDRESS,DISPLAY -u $user ${pkgs.libnotify}/bin/notify-send -u critical "BorgBackup Failed!" "Run journalctl -u borgbackup-job* for more details."
echo "sent notification"
fi
done
'' + lib.optionalString (cfg.OnFailureMail != null) ''
journalctl -u borgbackup-job-hetzner.service | ${pkgs.mailutils}/bin/mail -r "Administrator<root@buehler.rocks>" -s "Backup Error" server@buehler.rocks
echo "sent mail"
'' + ''
fi
'';
startAt = "daily";
persistentTimer = true;
prune.keep = {
last = 1;
within = "3d";
daily = 7;
weekly = 4;
monthly = 6;
yearly = 2;
};
};
};
}

View file

@ -1,6 +1,7 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
./backup
./gitea ./gitea
./hedgedoc ./hedgedoc
./homepage ./homepage

View file

@ -1,79 +0,0 @@
{ config, lib, pkgs, ... }:
let
borgbackupPath = "u181505-sub1@u181505-sub1.your-storagebox.de";
borgbackupMonitor = { config, pkgs, lib, ... }: with lib; {
key = "borgbackupMonitor";
_file = "borgbackupMonitor";
config.systemd.services = {
"notify-problems@" = {
enable = true;
serviceConfig.User = "felix";
environment.SERVICE = "%i";
script = ''
export $(cat /proc/$(${pkgs.procps}/bin/pgrep -x "sway" -u "$USER")/environ |grep -z '^DBUS_SESSION_BUS_ADDRESS=')
${pkgs.libnotify}/bin/notify-send -u critical "$SERVICE FAILED!" "Run journalctl -u $SERVICE for details"
'';
};
} // flip mapAttrs' config.services.borgbackup.jobs (name: value:
nameValuePair "borgbackup-job-${name}" {
unitConfig.OnFailure = "notify-problems@%i.service";
}
);
};
in
{
# notification
imports = [
borgbackupMonitor
];
sops.secrets."borgbackup/password" = { };
sops.secrets."borgbackup/private_ssh_key" = { };
services.borgbackup.jobs.hetzner = {
paths = [
"/"
];
exclude = [
"/nix"
"/sys"
"/run"
"/proc"
"/root/.cache/"
"**/.Trash"
"/tmp"
"/var/lock"
"/var/lib/docker/devicemapper"
"/var/run"
"/var/tmp"
"/srv/data/tmp"
"/srv/data/todo"
"/home/*/.gvfs"
"/home/*/tmp"
"/home/*/todo"
"sh:/home/*/.cache"
"sh:/home/*/.local/share/Trash"
"sh:/home/*/.thumbnails"
];
extraCreateArgs = "--exclude-caches --keep-exclude-tags --stats";
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${config.sops.secrets."borgbackup/password".path}";
};
environment.BORG_RSH = "ssh -o 'StrictHostKeyChecking=no' -i ${config.sops.secrets."borgbackup/private_ssh_key".path} -p 23";
repo = borgbackupPath + ":${config.networking.hostName}/";
compression = "auto,zstd";
doInit = false;
startAt = "daily";
persistentTimer = true;
prune.keep = {
last = 1;
within = "3d";
daily = 7;
weekly = 4;
monthly = 6;
yearly = 2;
};
};
}

View file

@ -1,79 +0,0 @@
{ config, lib, pkgs, ... }:
let
borgbackupPath = "u181505-sub1@u181505-sub1.your-storagebox.de:serverle/";
borgbackupMonitor = { config, pkgs, lib, ... }: with lib; {
key = "borgbackupMonitor";
_file = "borgbackupMonitor";
config.systemd.services = {
"notify-problems@" = {
enable = true;
serviceConfig.User = "felix";
environment.SERVICE = "%i";
script = ''
export $(cat /proc/$(${pkgs.procps}/bin/pgrep -x "sway" -u "$USER")/environ |grep -z '^DBUS_SESSION_BUS_ADDRESS=')
${pkgs.libnotify}/bin/notify-send -u critical "$SERVICE FAILED!" "Run journalctl -u $SERVICE for details"
'';
};
} // flip mapAttrs' config.services.borgbackup.jobs (name: value:
nameValuePair "borgbackup-job-${name}" {
unitConfig.OnFailure = "notify-problems@%i.service";
}
);
};
in
{
# notification
imports = [
borgbackupMonitor
];
sops.defaultSopsFile = ./secrets.yaml;
sops.secrets."borgbackup/password" = { };
sops.secrets."borgbackup/private_ssh_key" = { };
services.borgbackup.jobs.hetzner = {
paths = [
"/"
];
exclude = [
"/nix"
"/sys"
"/run"
"/proc"
"/root/.cache/"
"**/.Trash"
"/tmp/*"
"/var/lock/*"
"/var/run/*"
"/var/tmp/*"
"/home/*/tmp"
"/home/*/todo"
"/home/*/.cache"
"/home/*/.gvfs"
"/home/*/.thumbnails"
"/home/*/.local/share/Trash"
"/srv/data/tmp"
"/srv/data/todo"
];
extraCreateArgs = "--exclude-caches --keep-exclude-tags --stats";
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${config.sops.secrets."borgbackup/password".path}";
};
environment.BORG_RSH = "ssh -o 'StrictHostKeyChecking=no' -i ${config.sops.secrets."borgbackup/private_ssh_key".path} -p 23";
repo = borgbackupPath;
compression = "auto,zstd";
doInit = false;
startAt = "daily";
persistentTimer = true;
prune.keep = {
last = 1;
within = "3d";
daily = 7;
weekly = 4;
monthly = 6;
yearly = 2;
};
};
}

View file

@ -4,8 +4,18 @@ let
secrets = config.sops.secrets; secrets = config.sops.secrets;
in in
{ {
sops.secrets."borgbackup/password" = { };
sops.secrets."borgbackup/private_ssh_key" = { };
# List services that you want to enable: # List services that you want to enable:
my.services = { my.services = {
backup = {
enable = true;
OnFailureMail = "server@buehler.rocks";
passwordFile = secrets."borgbackup/password".path;
sshKeyFile = secrets."borgbackup/private_ssh_key".path;
};
ssh-server = { ssh-server = {
enable = true; enable = true;
}; };

View file

@ -3,10 +3,10 @@
imports = [ imports = [
./disks.nix ./disks.nix
./hardware-configuration.nix ./hardware-configuration.nix
./services.nix
../modules/3d-design.nix ../modules/3d-design.nix
../modules/android.nix ../modules/android.nix
../modules/avahi.nix ../modules/avahi.nix
../modules/backup.nix
../modules/bluetooth-audio.nix ../modules/bluetooth-audio.nix
../modules/clean.nix ../modules/clean.nix
../modules/desktop-default.nix ../modules/desktop-default.nix

View file

@ -0,0 +1,19 @@
# Deployed services
{ config, lib, ... }:
let
secrets = config.sops.secrets;
in
{
sops.secrets."borgbackup/password" = { };
sops.secrets."borgbackup/private_ssh_key" = { };
# List services that you want to enable:
my.services = {
backup = {
enable = true;
OnFailureNotification = true;
passwordFile = secrets."borgbackup/password".path;
sshKeyFile = secrets."borgbackup/private_ssh_key".path;
};
};
}