restic: Prepare for additional backups
This commit is contained in:
parent
7a72bf8b0d
commit
50823a746e
|
@ -19,7 +19,9 @@
|
||||||
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;
|
||||||
|
backups.system = {
|
||||||
enable = true;
|
enable = true;
|
||||||
qos = true;
|
qos = true;
|
||||||
extraPaths = [
|
extraPaths = [
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
"/data/torrent"
|
"/data/torrent"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
};
|
||||||
unfree.allowSoftware = true;
|
unfree.allowSoftware = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sbruder.restic.system.extraExcludes = [
|
sbruder.restic.backups.system.extraExcludes = [
|
||||||
"/var/lib/private/photoprism"
|
"/var/lib/private/photoprism"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -19,13 +19,16 @@
|
||||||
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;
|
||||||
|
backups.system = {
|
||||||
enable = true;
|
enable = true;
|
||||||
qos = true;
|
qos = true;
|
||||||
extraPaths = [
|
extraPaths = [
|
||||||
"/data"
|
"/data"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
};
|
||||||
unfree.allowSoftware = true;
|
unfree.allowSoftware = true;
|
||||||
wireguard.home.enable = true;
|
wireguard.home.enable = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,10 +19,13 @@
|
||||||
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;
|
||||||
|
backups.system = {
|
||||||
enable = true;
|
enable = true;
|
||||||
qos = true;
|
qos = true;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
unfree.allowSoftware = true;
|
unfree.allowSoftware = true;
|
||||||
wireguard.home.enable = true;
|
wireguard.home.enable = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,10 +13,13 @@
|
||||||
|
|
||||||
sbruder = {
|
sbruder = {
|
||||||
gui.enable = true;
|
gui.enable = true;
|
||||||
restic.system = {
|
restic = {
|
||||||
|
enable = true;
|
||||||
|
backups.system = {
|
||||||
enable = true;
|
enable = true;
|
||||||
qos = true;
|
qos = true;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
unfree.allowSoftware = true;
|
unfree.allowSoftware = true;
|
||||||
wireguard.home.enable = true;
|
wireguard.home.enable = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 host’s cgroups are not available,
|
# where the target host’s 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
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue