restic: Prepare for additional backups

This commit is contained in:
Simon Bruder 2024-08-22 16:13:13 +02:00
parent 7a72bf8b0d
commit 50823a746e
Signed by: simon
GPG key ID: 347FF8699CDA0776
11 changed files with 123 additions and 80 deletions

View file

@ -19,20 +19,23 @@
wireguard.home.enable = true; wireguard.home.enable = true;
nginx.hardening.enable = true; nginx.hardening.enable = true;
printing.server.enable = true; printing.server.enable = true;
restic.system = { restic = {
enable = true; enable = true;
qos = true; backups.system = {
extraPaths = [ enable = true;
"/data" qos = true;
]; extraPaths = [
extraExcludes = [ "/data"
"/data/cold/media/video" ];
"/data/cold/misc" extraExcludes = [
"/data/cold/torrent" "/data/cold/media/video"
"/data/hot/torrent" "/data/cold/misc"
"/data/media/video" "/data/cold/torrent"
"/data/torrent" "/data/hot/torrent"
]; "/data/media/video"
"/data/torrent"
];
};
}; };
unfree.allowSoftware = true; unfree.allowSoftware = true;
}; };

View file

@ -13,7 +13,7 @@
}; };
}; };
sbruder.restic.system.extraExcludes = [ sbruder.restic.backups.system.extraExcludes = [
"/var/lib/private/photoprism" "/var/lib/private/photoprism"
]; ];

View file

@ -12,7 +12,10 @@
sbruder = { sbruder = {
full = false; full = false;
restic.system.enable = true; restic = {
enable = true;
backups.system.enable = true;
};
wireguard.home.enable = true; wireguard.home.enable = true;
infovhost.enable = true; infovhost.enable = true;
nginx = { nginx = {

View file

@ -19,12 +19,15 @@
gui.enable = true; gui.enable = true;
media-proxy.enable = true; media-proxy.enable = true;
podman.enable = true; podman.enable = true;
restic.system = { restic = {
enable = true; enable = true;
qos = true; backups.system = {
extraPaths = [ enable = true;
"/data" qos = true;
]; extraPaths = [
"/data"
];
};
}; };
unfree.allowSoftware = true; unfree.allowSoftware = true;
wireguard.home.enable = true; wireguard.home.enable = true;

View file

@ -12,7 +12,10 @@
]; ];
sbruder = { sbruder = {
restic.system.enable = true; restic = {
enable = true;
backups.system.enable = true;
};
wireguard.home.enable = true; wireguard.home.enable = true;
podman.enable = true; podman.enable = true;
}; };

View file

@ -19,9 +19,12 @@
gui.enable = true; gui.enable = true;
media-proxy.enable = true; media-proxy.enable = true;
podman.enable = true; podman.enable = true;
restic.system = { restic = {
enable = true; enable = true;
qos = true; backups.system = {
enable = true;
qos = true;
};
}; };
unfree.allowSoftware = true; unfree.allowSoftware = true;
wireguard.home.enable = true; wireguard.home.enable = true;

View file

@ -13,9 +13,12 @@
sbruder = { sbruder = {
gui.enable = true; gui.enable = true;
restic.system = { restic = {
enable = true; enable = true;
qos = true; backups.system = {
enable = true;
qos = true;
};
}; };
unfree.allowSoftware = true; unfree.allowSoftware = true;
wireguard.home.enable = true; wireguard.home.enable = true;

View file

@ -27,9 +27,10 @@
sbruder = { sbruder = {
nginx.hardening.enable = true; nginx.hardening.enable = true;
restic.system = { restic = {
enable = true; enable = true;
prune = true; backups.system.enable = true;
prune.enable = true;
}; };
wireguard.home.enable = true; wireguard.home.enable = true;
infovhost.enable = true; infovhost.enable = true;

View file

@ -17,7 +17,10 @@
sbruder = { sbruder = {
nginx.hardening.enable = true; nginx.hardening.enable = true;
restic.system.enable = true; restic = {
enable = true;
backups.system.enable = true;
};
wireguard.home.enable = true; wireguard.home.enable = true;
full = false; full = false;
infovhost.enable = true; infovhost.enable = true;

View file

@ -1,9 +1,78 @@
# SPDX-FileCopyrightText: 2020-2021 Simon Bruder <simon@sbruder.de> # SPDX-FileCopyrightText: 2020-2024 Simon Bruder <simon@sbruder.de>
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
{ config, lib, pkgs, ... }:
let
cfg = config.sbruder.restic;
sftpTarget = "u313368-sub4@u313368-sub4.your-storagebox.de";
sftpPort = 23;
repository = "sftp://${sftpTarget}:${toString sftpPort}/personal";
mkPruneConfig = { tag, timerConfig }: {
inherit repository timerConfig;
passwordFile = config.sops.secrets.restic-password.path;
paths = [ ];
extraOptions = [
"-o"
"sftp.command='ssh -i ${config.sops.secrets.restic-ssh-key.path} -p ${toString sftpPort} ${sftpTarget} -s sftp'"
];
pruneOpts = [
"--compression auto"
"--keep-daily 7"
"--keep-monthly 12"
"--keep-weekly 5"
"--keep-yearly 10"
"--tag ${tag}"
"--verbose"
];
};
in
{ {
imports = [ imports = [
./system.nix ./system.nix
]; ];
options.sbruder.restic = {
enable = lib.mkEnableOption "restic";
authScript.enable = (lib.mkEnableOption "script to use restic as user without dealing with authentication") // {
default = cfg.enable && config.sbruder.gui.enable;
};
prune.enable = lib.mkEnableOption "pruning";
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
sops.secrets = {
restic-password = { };
restic-repository = { };
};
}
(lib.mkIf cfg.authScript.enable {
environment.systemPackages = [
(pkgs.writeShellScriptBin "restic-auth" ''
${pkgs.restic}/bin/restic \
--password-command="pass data/backup/restic-nixos" \
--repo "${repository}" \
$@
'')
];
})
(lib.mkIf cfg.prune.enable {
sops.secrets.restic-ssh-key = {
sopsFile = ../../machines/${config.networking.hostName}/secrets.yaml;
};
services.restic.backups = {
system-prune = mkPruneConfig {
tag = "system";
timerConfig = {
OnCalendar = "*-1/2-07 03:00:00";
RandomizedDelaySec = "4h";
};
};
};
})
]);
} }

View file

@ -4,11 +4,8 @@
{ pkgs, config, lib, ... }: { pkgs, config, lib, ... }:
let let
cfg = config.sbruder.restic.system; cfg = config.sbruder.restic.backups.system;
sftpTarget = "u313368-sub4@u313368-sub4.your-storagebox.de";
sftpPort = 23;
repository = "sftp://${sftpTarget}:${toString sftpPort}/personal";
excludes = [ excludes = [
# Caches # Caches
"/home/*/Downloads/" "/home/*/Downloads/"
@ -37,14 +34,6 @@ let
] ++ cfg.extraExcludes; ] ++ cfg.extraExcludes;
excludesFile = pkgs.writeText "excludes.txt" (lib.concatStringsSep "\n" excludes); excludesFile = pkgs.writeText "excludes.txt" (lib.concatStringsSep "\n" excludes);
# script to use restic as user without dealing with authentication
authScript = pkgs.writeShellScriptBin "restic-auth" ''
${pkgs.restic}/bin/restic \
--password-command="pass data/backup/restic-nixos" \
--repo "${repository}" \
$@
'';
# HACK: NixOS nftables implementation runs nft -c inside the build sandbox, # HACK: NixOS nftables implementation runs nft -c inside the build sandbox,
# where the target hosts cgroups are not available, # where the target hosts cgroups are not available,
# and therefore fails. # and therefore fails.
@ -65,8 +54,8 @@ let
''; '';
in in
{ {
options.sbruder.restic.system = { options.sbruder.restic.backups.system = {
enable = lib.mkEnableOption "restic"; enable = lib.mkEnableOption "restic system backup";
timerConfig = lib.mkOption { timerConfig = lib.mkOption {
type = with lib.types; attrsOf str; type = with lib.types; attrsOf str;
default = { default = {
@ -88,19 +77,9 @@ in
default = null; default = null;
}; };
qos = (lib.mkEnableOption "QoS marking (DSCP AF12) of outgoing packets") // { default = !(isNull cfg.uploadLimit); }; qos = (lib.mkEnableOption "QoS marking (DSCP AF12) of outgoing packets") // { default = !(isNull cfg.uploadLimit); };
prune = lib.mkEnableOption "pruning";
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
sops.secrets = {
restic-password = { };
restic-repository = { };
} // lib.optionalAttrs cfg.prune {
restic-ssh-key = {
sopsFile = ../../machines/${config.networking.hostName}/secrets.yaml;
};
};
services.restic.backups.system = { services.restic.backups.system = {
inherit (cfg) timerConfig; inherit (cfg) timerConfig;
repositoryFile = config.sops.secrets.restic-repository.path; repositoryFile = config.sops.secrets.restic-repository.path;
@ -134,32 +113,5 @@ in
"IOSchedulingPriority" = 7; "IOSchedulingPriority" = 7;
Slice = "restic.slice"; Slice = "restic.slice";
}; };
services.restic.backups.system-prune = lib.mkIf cfg.prune {
inherit repository;
passwordFile = config.sops.secrets.restic-password.path;
timerConfig = {
OnCalendar = "*-1/2-07 03:00:00";
RandomizedDelaySec = "4h";
};
paths = [ ];
extraOptions = [
"-o"
"sftp.command='ssh -i ${config.sops.secrets.restic-ssh-key.path} -p ${toString sftpPort} ${sftpTarget} -s sftp'"
];
pruneOpts = [
"--compression auto"
"--keep-daily 7"
"--keep-monthly 12"
"--keep-weekly 5"
"--keep-yearly 10"
"--tag system"
"--verbose"
] ++ lib.optional (cfg.uploadLimit != null) "--limit-upload=${toString cfg.uploadLimit}";
};
environment.systemPackages = [
authScript
];
}; };
} }