Switch to backing up to hetzner storage box #99
|
@ -24,6 +24,24 @@
|
||||||
inherit name text;
|
inherit name text;
|
||||||
runtimeInputs = packages;
|
runtimeInputs = packages;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
# *NOT* a TOML file, for some reason quotes are interpreted
|
||||||
|
# *literally
|
||||||
|
rcloneConfig = pkgs.writeText "rclone.conf" ''
|
||||||
|
[storagebox]
|
||||||
|
type = sftp
|
||||||
|
user = u395933
|
||||||
|
host = u395933.your-storagebox.de
|
||||||
|
port = 23
|
||||||
|
key_file = ${config.sops.secrets."restic/storagebox-ssh-key".path}
|
||||||
|
shell_type = unix
|
||||||
|
'';
|
||||||
|
|
||||||
|
resticEnv = {
|
||||||
|
RESTIC_PASSWORD_FILE = config.sops.secrets."restic/storagebox-backups".path;
|
||||||
|
RESTIC_REPOSITORY = "rclone:storagebox:backups";
|
||||||
|
RCLONE_CONFIG = rcloneConfig;
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
services.backups = lib.mkOption {
|
services.backups = lib.mkOption {
|
||||||
|
@ -120,13 +138,11 @@ in {
|
||||||
# Doesn't hurt to finish the ongoing prune
|
# Doesn't hurt to finish the ongoing prune
|
||||||
restartIfChanged = false;
|
restartIfChanged = false;
|
||||||
|
|
||||||
environment = {
|
environment = resticEnv;
|
||||||
RESTIC_PASSWORD_FILE = config.sops.secrets."restic/local-backups".path;
|
|
||||||
RESTIC_REPOSITORY = "/var/lib/backups/";
|
|
||||||
RESTIC_CACHE_DIR = "%C/restic-prune";
|
|
||||||
};
|
|
||||||
|
|
||||||
path = with pkgs; [
|
path = with pkgs; [
|
||||||
|
openssh
|
||||||
|
rclone
|
||||||
restic
|
restic
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -145,11 +161,6 @@ in {
|
||||||
|
|
||||||
CacheDirectory = "restic-prune";
|
CacheDirectory = "restic-prune";
|
||||||
CacheDirectoryMode = "0700";
|
CacheDirectoryMode = "0700";
|
||||||
ReadWritePaths = "/var/lib/backups/";
|
|
||||||
|
|
||||||
# Ensure we don't leave behind any files with the
|
|
||||||
# temporary UID of this service.
|
|
||||||
ExecStopPost = "+${pkgs.coreutils}/bin/chown -R root:backup /var/lib/backups/";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -158,17 +169,24 @@ in {
|
||||||
# Don't want to restart mid-backup
|
# Don't want to restart mid-backup
|
||||||
restartIfChanged = false;
|
restartIfChanged = false;
|
||||||
|
|
||||||
environment = {
|
environment =
|
||||||
|
resticEnv
|
||||||
|
// {
|
||||||
RESTIC_CACHE_DIR = "%C/backup-${name}";
|
RESTIC_CACHE_DIR = "%C/backup-${name}";
|
||||||
RESTIC_PASSWORD_FILE = config.sops.secrets."restic/local-backups".path;
|
};
|
||||||
|
|
||||||
|
path = with pkgs; [
|
||||||
|
coreutils
|
||||||
|
openssh
|
||||||
|
rclone
|
||||||
|
restic
|
||||||
|
];
|
||||||
|
|
||||||
# TODO(tlater): If I ever add more than one repo, service
|
# TODO(tlater): If I ever add more than one repo, service
|
||||||
# shutdown/restarting will potentially break if multiple
|
# shutdown/restarting will potentially break if multiple
|
||||||
# backups for the same service overlap. A more clever
|
# backups for the same service overlap. A more clever
|
||||||
# sentinel file with reference counts would probably solve
|
# sentinel file with reference counts would probably solve
|
||||||
# this.
|
# this.
|
||||||
RESTIC_REPOSITORY = "/var/lib/backups/";
|
|
||||||
};
|
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
User = backup.user;
|
User = backup.user;
|
||||||
Group = "backup";
|
Group = "backup";
|
||||||
|
@ -183,8 +201,8 @@ in {
|
||||||
|
|
||||||
ExecStartPre =
|
ExecStartPre =
|
||||||
map (service: "+${mkShutdownScript service}") backup.pauseServices
|
map (service: "+${mkShutdownScript service}") backup.pauseServices
|
||||||
++ singleton (writeScript "backup-${name}-repo-init" [pkgs.restic pkgs.coreutils] ''
|
++ singleton (writeScript "backup-${name}-repo-init" [] ''
|
||||||
restic snapshots || (restic init && chmod -R g+rwx "$RESTIC_REPOSITORY"/*)
|
restic snapshots || restic init
|
||||||
'')
|
'')
|
||||||
++ optional (backup.preparation.text != null)
|
++ optional (backup.preparation.text != null)
|
||||||
(writeScript "backup-${name}-prepare" backup.preparation.packages backup.preparation.text);
|
(writeScript "backup-${name}-prepare" backup.preparation.packages backup.preparation.text);
|
||||||
|
@ -220,10 +238,14 @@ in {
|
||||||
})
|
})
|
||||||
config.services.backups;
|
config.services.backups;
|
||||||
|
|
||||||
users.groups.backup = {};
|
users = {
|
||||||
|
# This user is only used to own the ssh key, because apparently
|
||||||
systemd.tmpfiles.rules = [
|
# the ssh client checks file permissions and is stuck in 1980.
|
||||||
"d /var/lib/backups/ 0770 root backup"
|
users.backup = {
|
||||||
];
|
group = "backup";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
groups.backup = {};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
group = "backup";
|
group = "backup";
|
||||||
mode = "0440";
|
mode = "0440";
|
||||||
};
|
};
|
||||||
|
"restic/storagebox-backups" = {
|
||||||
|
owner = "root";
|
||||||
|
group = "backup";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
"restic/storagebox-ssh-key" = {
|
||||||
|
owner = "backup";
|
||||||
|
group = "backup";
|
||||||
|
mode = "0040";
|
||||||
|
};
|
||||||
|
|
||||||
# Steam
|
# Steam
|
||||||
"steam/tlater" = {};
|
"steam/tlater" = {};
|
||||||
|
|
|
@ -14,6 +14,8 @@ wireguard:
|
||||||
server-key: ENC[AES256_GCM,data:mXb7ZznJHf5CgV8rI4uzPBATMRbmd7LimgtCkQM9kAjbIaGwUBqJZBN3fXs=,iv:3Po1Orinzov9rnEm9cLzgJY1PeD+5Jl9115MriABHh8=,tag:E/2CjDO1JCvJzxCnqKcNyw==,type:str]
|
server-key: ENC[AES256_GCM,data:mXb7ZznJHf5CgV8rI4uzPBATMRbmd7LimgtCkQM9kAjbIaGwUBqJZBN3fXs=,iv:3Po1Orinzov9rnEm9cLzgJY1PeD+5Jl9115MriABHh8=,tag:E/2CjDO1JCvJzxCnqKcNyw==,type:str]
|
||||||
restic:
|
restic:
|
||||||
local-backups: ENC[AES256_GCM,data:NLNVlR9G9bLSZOkMoPvkbBbAZlKkmiUbdWHOFDnaefuy9wNLH53ctOIyS0rSsQLaJCSBTpgPSWIIXUSuzoK/eA==,iv:DzuujmyJJP4GiE5z7KOOGUEzUgOwmtf/7UYhwkyLe9g=,tag:cElFhpVC7S6HYlB6UyN7PQ==,type:str]
|
local-backups: ENC[AES256_GCM,data:NLNVlR9G9bLSZOkMoPvkbBbAZlKkmiUbdWHOFDnaefuy9wNLH53ctOIyS0rSsQLaJCSBTpgPSWIIXUSuzoK/eA==,iv:DzuujmyJJP4GiE5z7KOOGUEzUgOwmtf/7UYhwkyLe9g=,tag:cElFhpVC7S6HYlB6UyN7PQ==,type:str]
|
||||||
|
storagebox-backups: ENC[AES256_GCM,data:UyT8jCkKlfYJXjWLI9MbYfeVhY5d89N3aj1Olj54/aBOP3gwcrx6gU56Pwa1xKZ3lR13AVs/b4wF9sbvP7Kqqg==,iv:0HM+DgH4iCiWpjRvAYCFQGEy4xIBQwAM+PkkzOsizw0=,tag:jbrqo1In2O4jVM5e7fjOzg==,type:str]
|
||||||
|
storagebox-ssh-key: ENC[AES256_GCM,data:7aYlKX7I8Bsur3nm4nV9eSW3lmIxBCeCUMbPX3qgcotPbyPYaUqD3MOCnFRepajYkFXAgMX4jknqLfoO9xYc4bavDFjOY8Ww/KmLay7ces6tDnkK6tTRxcNRPUBqEzaFiPNsZc2UwHnmHOF0rKvQusvhCOplYao3xxz5McTHC7IEriUApSNudWCg3qGbyAmxkGEw7tRfh6IiUXEOFeaXDZd78dWZlWIIeospmA1hcVhkLGrjMmoikt/YANHUpWPbd+B9E6x+s2eIzFdvztRjarBluWPZuX981b+hcOm1/+HY/tJ/jzgyVbX1rjmdgZ9jZqdKO/vkOkijHWXlwpQ0QJ2s8p5MURPGRsC7W5jfmGbVKrubxfQC2mSJRJgBaj1wX3yI4GbfCXNdbpseAMy7t8OmN/iMN57lGnD3uX8CWWD327PIWp3SgwMDIZtJRlMBu3vMUrBdNnrrlYoLgf821tX7JWW6L5g1EK/bcBZqZZ/6rE+Q9fLiJHTsj2lyTzQZRLKsn0YePlcIMOWHO2CG/aWrfycdSKKjaKGG,iv:OVnEIMFB4h/EQ8zV3XOpVXLDrV5t4roNYDFQz99m4sQ=,tag:mKWF12uD1TLla/MoJs2zNg==,type:str]
|
||||||
turn:
|
turn:
|
||||||
env: ENC[AES256_GCM,data:kt5nhVo9pb/ZbPUEcqSYXxN9YMgQKnFb5VRfFFS/qoIaJ73uD2fuJKqcxAyVRrdLqnSAWSQBgTgunBzdP7xqLAK2qt8DYAQWHkIe9uxFbSXZpdmw,iv:9lq6SFwTFN4GGm6gPiJpUMasMdnHVF6XLGYrsyG3kjU=,tag:428Qf9DOiiHt/Wjb188b8g==,type:str]
|
env: ENC[AES256_GCM,data:kt5nhVo9pb/ZbPUEcqSYXxN9YMgQKnFb5VRfFFS/qoIaJ73uD2fuJKqcxAyVRrdLqnSAWSQBgTgunBzdP7xqLAK2qt8DYAQWHkIe9uxFbSXZpdmw,iv:9lq6SFwTFN4GGm6gPiJpUMasMdnHVF6XLGYrsyG3kjU=,tag:428Qf9DOiiHt/Wjb188b8g==,type:str]
|
||||||
secret: ENC[AES256_GCM,data:si7ee6Xfhdgdyzbp6aQpF7pz3TmTBb7iQ82lRPVXNDg9JfHI+lbmgAsSnRLX5qMCA6P9R045sSMosqidL8QwRg==,iv:SrhpZKK8D45yxCEfDb9P3TwtA14+qEI+wcRqcN/a6pw=,tag:PiwV+mOL9xHJgJft6sc61g==,type:str]
|
secret: ENC[AES256_GCM,data:si7ee6Xfhdgdyzbp6aQpF7pz3TmTBb7iQ82lRPVXNDg9JfHI+lbmgAsSnRLX5qMCA6P9R045sSMosqidL8QwRg==,iv:SrhpZKK8D45yxCEfDb9P3TwtA14+qEI+wcRqcN/a6pw=,tag:PiwV+mOL9xHJgJft6sc61g==,type:str]
|
||||||
|
@ -26,8 +28,8 @@ sops:
|
||||||
azure_kv: []
|
azure_kv: []
|
||||||
hc_vault: []
|
hc_vault: []
|
||||||
age: []
|
age: []
|
||||||
lastmodified: "2024-03-18T04:04:56Z"
|
lastmodified: "2024-03-18T04:05:08Z"
|
||||||
mac: ENC[AES256_GCM,data:qIbgeaaFQXYacURO9EVfvtvvlUP0j7FMJuh9CIRbzQCyoSedibt1yhGIMQk2ERUliPb8OEuG4QPZ8rled/DmP1BHrUNTYFnRcagtPOnIE+0b9TuAVrj+vTWVl4MvQKMt9i/DQJsWAZVuaP8isDuZ77mVnlj1V8F+1MvXtL0+ZVM=,iv:0mKgiXjWrmNmuXLEsPYBMWSZvD9qrHDHEkSPAm9GCY4=,tag:ZM32r6kbsi4ERGFERzTRpA==,type:str]
|
mac: ENC[AES256_GCM,data:/v/XRBizRUn8UR1HOIaKrY11/5I8RmsctmxXg0wcCXO983YgcGYTEqfXOSRJzkh/MOjB0c8jpdfE7tyqYgB2iYjm+HmRFVsGNB484e+3ukAMsxz4CTz26RWC/LEemQeBOa5RB3rrPXXo1LrJCBN9Y+T/PVgO2xshUSxyhRFQmMA=,iv:km1m8k/vrCVT8ugvqAZNORLu0NSW66B58btH5k4e//Y=,tag:RZXviobM03IQXN1FwDUlVA==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2024-03-18T04:02:00Z"
|
- created_at: "2024-03-18T04:02:00Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|
Loading…
Reference in a new issue