feat: some backups things maybe

This commit is contained in:
Ashhhleyyy 2025-01-25 17:12:08 +00:00
parent 69ab95197e
commit 6c2b4d830c
Signed by: ash
GPG key ID: 83B789081A0878FB
11 changed files with 133 additions and 1 deletions

View file

@ -45,5 +45,7 @@
services.aci-backend.enable = true;
forest.backups.enable = true;
system.stateVersion = "23.11";
}

108
modules/backups.nix Normal file
View file

@ -0,0 +1,108 @@
{
config,
lib,
...
}:
let
inherit (lib) mkEnableOption mkOption types mkIf optionalAttrs;
cfg = config.forest.backups;
in
{
options.forest.backups = {
enable = mkEnableOption "restic";
paths = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
description = lib.mdDoc ''
Which paths to backup. If null or an empty array, no
backup command will be run. This can be used to create a
prune-only job.
'';
example = ["/var/lib/postgresql" "/home/user/backup"];
};
exclude = mkOption {
type = types.listOf types.str;
default = [];
description = lib.mdDoc ''
Patterns to exclude when backing up.
'';
example = ["/var/cache" "/home/*/.cache" ".git"];
};
timerConfig = mkOption {
type = types.attrsOf unitOption;
default = {
OnCalendar = "*-*-* 4:00:00";
};
description = lib.mdDoc ''
When to run the backup. See man systemd.timer for details.
'';
example = {
OnCalendar = "00:05";
RandomizedDelaySec = "5h";
};
};
personal = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Limits the minimum run interval to 12h and only allows the job to run when connected to AC power.
'';
}
};
# somewhat inspired by https://github.com/diogotcorreia/dotfiles/blob/f49cda185cef30d8150a08b60112766f4fc95813/modules/services/restic.nix
# lots of stuff here is hardcoded to my setup though
config = mkIf cfg.enable (let
in
{
age.secrets."restic-key-${config.networking.hostName}".file = "../secrets/restic-key-${config.networking.hostName}.age";
age.secrets."restic-rclone-${config.networking.hostName}".file = "../secrets/restic-rclone-${config.networking.hostName}.age";
age.secrets."restic-password-${config.networking.hostName}".file = "../secrets/restic-password-${config.networking.hostName}.age";
services.restic.backups.forest-backup = {
repository = "rclone:backupserver:.";
initialize = true;
rcloneConfig = {
type = "sftp";
key_file = config.age.secrets."restic-key-${config.networking.hostName}".path;
};
rcloneConfigFile = config.age.secrets."restic-rclone-${config.networking.hostName}".path;
passwordFile = config.age.secrets."restic-password-${config.networking.hostName}".path;
pruneOpts =
[
"--keep-last 20"
"--keep-daily 7"
"--keep-weekly 4"
"--keep-monthly 6"
"--keep-yearly 3"
];
checkOpts = [
# ensure data integrity
"--read-data-subset=2.5%"
];
paths = cfg.paths;
exclude = cfg.exclude;
};
systemd.services.restic-backups-forest-backup =
{
# Only run when network is up
wants = ["network-online.target"];
after = ["network-online.target"];
}
// optionalAttrs (cfg.personal) {
# Configure backups for personal machines
# Only on AC (for laptops) and never more frequently than 12h
startLimitIntervalSec = 12 * 60 * 60; # 12h
startLimitBurst = 1;
unitConfig.ConditionACPower = "|true"; # | means trigger
};
})
}

View file

@ -1,5 +1,6 @@
{ ... }: {
imports = [
./backups.nix
./pg-vacuum.nix
];
}

View file

@ -37,7 +37,7 @@ in
};
onCalendar = mkOption {
type = types.str;
default = "*-*-* 4:00:00";
default = "*-*-* 2:00:00";
description = ''
The interval between vacuum runs, the default value runs the vacuum job every day at 4am.

View file

@ -29,4 +29,6 @@
output file /var/log/caddy/sandbox.isnt-a.top-access.log
}
'';
services.postgresqlBackup.databases = ["gotosocial"];
}

View file

@ -46,4 +46,12 @@
enable = true;
runAsLocalSuperUser = true;
};
services.postgresqlBackup = {
enable = true;
# databases = ["shorks-gay"];
startAt = "*-*-* 03:00:00";
};
forest.backups.paths = ["/var/backups/postgresql"];
}

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKQpLt04cqf39n3ogxZoIcYRgfSJtoz5c3ft7aw7VdAh backups+amy@infra.isnt-a.top

BIN
secrets/restic-key-amy.age Normal file

Binary file not shown.

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 CEw3Tw 7ow8BVQK4sMIu+r3eLL7ZqCwrf+oLsj1S9gmO6a2fkM
X0dLPouaq9mXNj+tviTG4KyiQmoaxs7CLn0pCMRY7oA
-> ssh-ed25519 8o9woQ 2xvgMFGwY8+m9oIPJ6GIw3+8+/cEWr2XC8WwO48qW18
/06TtS4IUaVGIc4kKQmcORLKEQX+52qw6gJ8YZ3UtCk
--- DM7qS0vWgMJPlQ7ZNHUYfDiy0L1HlLcKwWrRIIHVG6c
¤†<EFBFBD>ôÂ|{&<26>qÜN<C39C>ÐtQŠ…Ö/þñjÊ$͈S¸·RS®õà#×½ã¿FÞH.RÝv/eh¶5Ôê´u<Ѫ¯!GoD %ìV'âNæ"]‘ŽédË3„“ز¶MËT¶¥àFÁ*|Zëy·Á I"ðtýÂ#DÂé;ìÐ^ÈŒ‡ÎnÔE<C394>Ž×A}zêaõäî|ËD̾B˜

Binary file not shown.

View file

@ -11,4 +11,7 @@ in
"zulip-redis.age".publicKeys = users ++ systems;
"zulip-env.age".publicKeys = users ++ systems;
"gts-sandbox.age".publicKeys = users ++ systems;
"restic-key-amy.age".publicKeys = users ++ [amy];
"restic-rclone-amy.age".publicKeys = users ++ [amy];
"restic-password-amy.age".publicKeys = users ++ [amy];
}