nixos-config/modules/restic/system.nix

130 lines
3.4 KiB
Nix

{ pkgs, config, lib, ... }:
let
cfg = config.sbruder.restic.system;
sftpTarget = "u313368-sub4@u313368-sub4.your-storagebox.de";
sftpPort = 23;
repository = "sftp://${sftpTarget}:${toString sftpPort}/personal";
excludes = [
# Caches
"/home/*/Downloads/"
"/home/*/.cache/"
"/home/*/**/cache/"
"/home/*/.local/share/Trash" # some gui applications use it
"/root/.cache"
"/data/cache/"
"/var/cache/"
# Rust
"/home/*/.rustup/toolchains/"
"/home/*/.cargo"
# Misc
"/home/*/mount"
"/home/*/mounts"
# Docker (state should be kept somewhere else)
"/var/lib/docker/"
# Static configuration (generated from this repository)
"/etc/static/"
] ++ cfg.extraExcludes;
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}" \
$@
'';
in
{
options.sbruder.restic.system = {
enable = lib.mkEnableOption "restic";
timerConfig = lib.mkOption {
type = with lib.types; attrsOf str;
default = {
OnCalendar = "18:00";
RandomizedDelaySec = "2h";
};
};
extraPaths = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "/data" ];
};
extraExcludes = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
uploadLimit = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = 1500;
};
prune = lib.mkEnableOption "pruning";
};
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 = {
inherit (cfg) timerConfig;
repositoryFile = config.sops.secrets.restic-repository.path;
passwordFile = config.sops.secrets.restic-password.path;
paths = [
"/etc"
"/home"
"/root"
"/srv"
"/var"
] ++ cfg.extraPaths;
extraBackupArgs = [
"--exclude-caches"
"--exclude-file=${excludesFile}"
"--tag system"
"--verbose"
] ++ lib.optional (cfg.uploadLimit != null) "--limit-upload=${toString cfg.uploadLimit}";
};
systemd.services."restic-backups-system".serviceConfig = {
"Nice" = 10;
"IOSchedulingClass" = "best-effort";
"IOSchedulingPriority" = 7;
};
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 = [
"--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
];
};
}