modules/backup: create a wrapper to handle restic failures

- create wrapper module
- expose po_env to everything
This commit is contained in:
Aaron Bieber 2024-07-31 09:52:49 -06:00
parent df63c1bb6a
commit 730fec96bb
No known key found for this signature in database
10 changed files with 166 additions and 66 deletions

View File

@ -42,7 +42,6 @@ with lib; {
config = mkIf config.xinCI.enable { config = mkIf config.xinCI.enable {
sops.defaultSopsFile = config.xin-secrets.ci; sops.defaultSopsFile = config.xin-secrets.ci;
sops.secrets = { sops.secrets = {
po_env = { owner = config.xinCI.user; };
ci_ed25519_key = { ci_ed25519_key = {
mode = "400"; mode = "400";
owner = config.xinCI.user; owner = config.xinCI.user;

View File

@ -36,7 +36,6 @@ with lib; {
manager_pubkey = { owner = config.nixManager.user; }; manager_pubkey = { owner = config.nixManager.user; };
ca_key = { owner = config.nixManager.user; }; ca_key = { owner = config.nixManager.user; };
ca_cert = { owner = config.nixManager.user; }; ca_cert = { owner = config.nixManager.user; };
po_env = { owner = config.nixManager.user; };
}; };
environment.systemPackages = [ environment.systemPackages = [

View File

@ -243,10 +243,6 @@ with lib; {
owner = config.nixManager.user; owner = config.nixManager.user;
sopsFile = config.xin-secrets.manager; sopsFile = config.xin-secrets.manager;
}; };
po_env = {
owner = config.nixManager.user;
sopsFile = config.xin-secrets.manager;
};
}; };
systemd.services = mkIf enabled (listToAttrs (builtins.map xinlib.jobToService jobs)); systemd.services = mkIf enabled (listToAttrs (builtins.map xinlib.jobToService jobs));
environment.systemPackages = mkIf enabled [ aclUpdateScript ]; environment.systemPackages = mkIf enabled [ aclUpdateScript ];

View File

@ -65,6 +65,11 @@ in
secrets = secrets =
if config.needsDeploy.enable then { if config.needsDeploy.enable then {
po_env = {
sopsFile = config.xin-secrets.deploy;
owner = "root";
mode = "444";
};
xin_secrets_deploy_key = { xin_secrets_deploy_key = {
sopsFile = config.xin-secrets.deploy; sopsFile = config.xin-secrets.deploy;
owner = "root"; owner = "root";

View File

@ -132,7 +132,10 @@
, ... , ...
} @ inputs: } @ inputs:
let let
xinlib = import ./lib { inherit (unstable) lib; }; xinlib = import ./lib {
inherit (unstable) lib;
inherit inputs;
};
supportedSystems = [ "x86_64-linux" ]; supportedSystems = [ "x86_64-linux" ];
#[ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; #[ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
forAllSystems = unstable.lib.genAttrs supportedSystems; forAllSystems = unstable.lib.genAttrs supportedSystems;

View File

@ -219,33 +219,31 @@ in
openFirewall = true; openFirewall = true;
}; };
printing.enable = true; printing.enable = true;
restic = { backups =
backups = let
let paths = [ "/home/qbit" "/etc" ];
paths = [ "/home/qbit" "/var/lib/libvirt" "/etc" ]; pruneOpts = [ "--keep-hourly 12" "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 4" ];
in timerConfig = { OnCalendar = "*-*-* 00:30:00"; };
{ in
remote = { {
initialize = true; remote = {
passwordFile = "${config.sops.secrets.restic_remote_password_file.path}"; enable = true;
repositoryFile = "${config.sops.secrets.restic_remote_repo_file.path}"; passwordFile = "${config.sops.secrets.restic_remote_password_file.path}";
repositoryFile = "${config.sops.secrets.restic_remote_repo_file.path}";
inherit paths; # Don't send libvirt over the air-wire
inherit paths pruneOpts timerConfig;
pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 4" ];
};
local = {
initialize = true;
repository = "/run/media/qbit/backup/${config.networking.hostName}";
environmentFile = "${config.sops.secrets.restic_env_file.path}";
passwordFile = "${config.sops.secrets.restic_password_file.path}";
inherit paths;
pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 5" ];
};
}; };
}; local = {
enable = true;
repository = "/run/media/qbit/backup/${config.networking.hostName}";
environmentFile = "${config.sops.secrets.restic_env_file.path}";
passwordFile = "${config.sops.secrets.restic_password_file.path}";
paths = paths ++ [ "/var/lib/libvirt" ];
inherit pruneOpts timerConfig;
};
};
pcscd.enable = true; pcscd.enable = true;
vnstat.enable = true; vnstat.enable = true;
# clamav.updater.enable = true; # clamav.updater.enable = true;

View File

@ -489,33 +489,31 @@ in
]; ];
}; };
restic = { backups = {
backups = { b2 = {
b2 = { enable = true;
initialize = true; repository = "b2:cyaspanJicyeemJedMarlEjcasOmos";
repository = "b2:cyaspanJicyeemJedMarlEjcasOmos"; environmentFile = "${config.sops.secrets.restic_env_file.path}";
environmentFile = "${config.sops.secrets.restic_env_file.path}"; passwordFile = "${config.sops.secrets.restic_password_file.path}";
passwordFile = "${config.sops.secrets.restic_password_file.path}";
paths = [ paths = [
pgBackupDir pgBackupDir
"/var/lib/synapse/media_store" "/var/lib/synapse/media_store"
"/var/www" "/var/www"
"/home" "/home"
"/var/lib/yarr" "/var/lib/yarr"
"/var/lib/shiori" "/var/lib/shiori"
"/var/lib/gotosocial" "/var/lib/gotosocial"
"/var/lib/mcchunkie" "/var/lib/mcchunkie"
"/var/lib/heisenbridge" "/var/lib/heisenbridge"
"/var/lib/kogs" "/var/lib/kogs"
"/var/vmail" "/var/vmail"
"/var/dkim" "/var/dkim"
]; ];
timerConfig = { OnCalendar = "00:05"; }; timerConfig = { OnCalendar = "00:05"; };
pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 10" ]; pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 10" ];
};
}; };
}; };

View File

@ -275,18 +275,16 @@ in
server = "127.0.0.1:24800"; server = "127.0.0.1:24800";
}; };
}; };
restic = { backups = {
backups = { remote = {
remote = { enable = true;
initialize = true; environmentFile = "${config.sops.secrets.restic_env_file.path}";
environmentFile = "${config.sops.secrets.restic_env_file.path}"; passwordFile = "${config.sops.secrets.restic_password_file.path}";
passwordFile = "${config.sops.secrets.restic_password_file.path}"; repositoryFile = "${config.sops.secrets.restic_repo_file.path}";
repositoryFile = "${config.sops.secrets.restic_repo_file.path}";
paths = [ "/home/abieber" ]; paths = [ "/home/abieber" ];
pruneOpts = [ "--keep-daily 7" "--keep-weekly 2" "--keep-monthly 2" ]; pruneOpts = [ "--keep-daily 7" "--keep-weekly 2" "--keep-monthly 2" ];
};
}; };
}; };
rsyslogd = { rsyslogd = {

103
modules/backup.nix Normal file
View File

@ -0,0 +1,103 @@
{ lib, inputs, config, utils, pkgs, ... }:
with lib;
let
inherit (utils.systemdUtils.unitOptions) unitOption;
cfg = config.services.backups;
enabledBackups = filterAttrs (_: conf: conf.enable) cfg;
in
{
options = {
services.backups = mkOption {
description = "Backup configurations, wrapped to allow for notifications of failed backups.";
default = { };
type = with types; attrsOf (submodule ({ name, ... }: {
options = {
enable = mkEnableOption "Enable backup for ${name}";
passwordFile = mkOption {
type = path;
description = "Path to file containing password.";
};
repository = mkOption {
type = nullOr str;
default = null;
description = "optional path to repository (can also be specified in the repositoryFile.";
};
repositoryFile = mkOption {
type = nullOr path;
default = null;
description = "Path to repository file.";
};
environmentFile = mkOption {
type = nullOr str;
default = null;
description = "path to environment file";
};
paths = mkOption {
type = listOf str;
description = "List of paths to backup.";
default = [ ];
};
pruneOpts = mkOption {
type = listOf str;
description = "Options for 'restic forget'.";
default = [ "--keep-hourly 12" "--keep-daily 7" "--keep-weekly 5" "--keep-yearly 4" ];
};
timerConfig = mkOption {
type = nullOr (attrsOf unitOption);
description = "systemd.timer(5) settings for when to do the backup.";
default = {
OnCalendar = "daily";
Persistent = true;
};
};
};
}));
};
};
config = mkIf (enabledBackups != { }) {
services.restic.backups = mapAttrs'
(name: conf: nameValuePair
name
{
initialize = true;
inherit (conf) passwordFile repository repositoryFile paths pruneOpts timerConfig environmentFile;
})
enabledBackups;
systemd.services = mkMerge [
(mapAttrs'
(name: _: nameValuePair
"restic-backups-${name}-failed"
{
enable = true;
description = "Notification service for ${name}";
serviceConfig = {
Type = "oneshot";
};
script = ''
. ${config.sops.secrets.po_env.path}
PO=${inputs.po.packages.${pkgs.system}.po}/bin/po
$PO -title "restic-${name} backup failed!" -body "Please check the ${name} backup on ${config.networking.hostName}."
'';
})
enabledBackups)
(mapAttrs'
(name: _: nameValuePair
"restic-backups-${name}"
{
unitConfig.OnFailure = "restic-backups-${name}-failed.service";
})
enabledBackups)
];
};
}

View File

@ -1,5 +1,6 @@
{ ... }: { { ... }: {
imports = [ imports = [
./backup.nix
./golink.nix ./golink.nix
./gotosocial.nix ./gotosocial.nix
./lock-action.nix ./lock-action.nix