140 lines
4.2 KiB
Nix
140 lines
4.2 KiB
Nix
# SPDX-FileCopyrightText: 2020-2024 Simon Bruder <simon@sbruder.de>
|
|
#
|
|
# 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, opts }: {
|
|
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"
|
|
"--tag ${tag}"
|
|
"--verbose"
|
|
] ++ opts;
|
|
};
|
|
in
|
|
{
|
|
imports = [
|
|
./system.nix
|
|
./vm-image.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";
|
|
mirror.backblaze.enable = lib.mkEnableOption "mirroring to Backblaze B2";
|
|
};
|
|
|
|
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";
|
|
};
|
|
opts = [
|
|
"--keep-daily 7"
|
|
"--keep-monthly 12"
|
|
"--keep-weekly 5"
|
|
"--keep-yearly 10"
|
|
];
|
|
};
|
|
|
|
vm-image-prune = mkPruneConfig {
|
|
tag = "vm-image";
|
|
timerConfig = {
|
|
OnCalendar = "06:00";
|
|
RandomizedDelaySec = "1h";
|
|
};
|
|
opts = [
|
|
"--keep-last 1"
|
|
];
|
|
};
|
|
};
|
|
})
|
|
(lib.mkIf cfg.mirror.backblaze.enable {
|
|
sops.secrets = {
|
|
restic-ssh-key.sopsFile = ../../machines/${config.networking.hostName}/secrets.yaml;
|
|
restic-mirror-backblaze-env.sopsFile = ../../machines/${config.networking.hostName}/secrets.yaml;
|
|
};
|
|
|
|
systemd.services.restic-mirror-backblaze = {
|
|
wants = [ "network-online.target" ];
|
|
after = [ "network-online.target" ];
|
|
|
|
serviceConfig = {
|
|
ExecStart = "${pkgs.rclone}/bin/rclone --config /dev/null sync :sftp,user=u313368-sub4,host=u313368-sub4.your-storagebox.de,port=23,key_file=$CREDENTIALS_DIRECTORY/ssh-key: :b2:sbruder-restic";
|
|
EnvironmentFile = config.sops.secrets.restic-mirror-backblaze-env.path;
|
|
|
|
LoadCredential = "ssh-key:${config.sops.secrets.restic-ssh-key.path}";
|
|
|
|
DynamicUser = true;
|
|
CapabilityBoundingSet = null;
|
|
LockPersonality = true;
|
|
MemoryDenyWriteExecute = true;
|
|
PrivateDevices = true;
|
|
PrivateUsers = true;
|
|
ProtectClock = true;
|
|
ProtectControlGroups = true;
|
|
ProtectHome = true;
|
|
ProtectHostname = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectProc = "noaccess";
|
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
|
RestrictNamespaces = true;
|
|
RestrictRealtime = true;
|
|
SystemCallArchitectures = "native";
|
|
SystemCallFilter = "@system-service";
|
|
};
|
|
};
|
|
|
|
systemd.timers.restic-mirror-backblaze = {
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnCalendar = "00/6:00:00";
|
|
RandomizedDelaySec = "2h";
|
|
};
|
|
};
|
|
})
|
|
]);
|
|
}
|