1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 14:50:40 +02:00

feat: add restic hetzner module, script still wip

This commit is contained in:
oddlama 2024-01-14 18:01:35 +01:00
parent 1165dc44aa
commit a464c99fb8
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
7 changed files with 106 additions and 0 deletions

View file

@ -160,6 +160,8 @@
;
}
// flake-utils.lib.eachDefaultSystem (system: rec {
apps.setupHetznerStorageBoxes = import ./nix/setup-hetzner-storage-boxes.nix self;
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;

View file

@ -80,6 +80,7 @@ in {
"rpool/local/state<" = true;
"rpool/safe<" = true;
"storage/safe<" = true;
"storage/bunker<" = true;
};
snapshotting = {
type = "periodic";

View file

@ -209,4 +209,37 @@ in {
];
users.groups = lib.mapAttrs (_: cfg: {gid = cfg.id;}) (smbUsers // smbGroups);
# Backups
# ========================================================================
age.secrets.restic-encryption-password.generator.script = "alnum";
age.secrets.restic-ssh-privkey.generator.script = "ssh-ed25519";
services.restic.backups.main = {
hetznerStorageBox = let
box = config.repo.secrets.global.hetzner.storageboxes.dusk;
in {
enable = true;
inherit (box) mainUser;
inherit (box.users.samba) subUid path;
sshPrivateKeyFile = config.age.secrets.restic-ssh-privkey.path;
};
user = "root";
timerConfig = {
OnCalendar = "06:15";
RandomizedDelaySec = "3h";
Persistent = true;
};
initialize = true;
passwordFile = config.age.secrets.restic-encryption-password.path;
paths = ["/bunker"];
pruneOpts = [
"--keep-daily 14"
"--keep-weekly 7"
"--keep-monthly 12"
"--keep-yearly 75"
];
};
}

View file

@ -34,6 +34,7 @@
./oauth2-proxy.nix
./promtail.nix
./provided-domains.nix
./restic.nix
./secrets.nix
./telegraf.nix
./wireguard-proxy.nix

57
modules/restic.nix Normal file
View file

@ -0,0 +1,57 @@
{lib, ...}: let
inherit
(lib)
mkEnableOption
mkIf
mkOption
types
;
in {
options.services.restic.backups = {
type = types.attrsOf (types.submodule ({config}: {
options.hetznerStorageBox = {
enable = mkEnableOption "Automatically configure this backup to use the given hetzner storage box. Will use SFTP via SSH.";
mainUser = mkOption {
type = types.str;
description = ''
The main user. While not technically required for restic, we still use it to
derive the subuser name and it is required for the automatic setup script
that creates the users.
'';
};
subUid = mkOption {
type = types.int;
description = "The id of the subuser that was allocated on the hetzner server for this backup.";
};
path = mkOption {
type = types.str;
description = ''
The remote path to backup into. While not technically required for restic
(since the subuser is chrooted on the remote), we'll still use it to set
a sane repository and it is required for the automatic setup script that
creates the users.
'';
};
sshPrivateKeyFile = {
type = types.path;
description = "The path to the ssh private key to use for uploading backups. Don't use a path from the nix store!";
};
};
config = let
subUser = "${config.hetznerStorageBox.mainUser}-sub${toString config.hetznerStorageBox.subUid}";
url = "${subUser}@${subUser}.your-storagebox.de";
in
mkIf config.hetznerStorageBox.enable {
repository = "sftp://${url}:23${config.hetznerStorageBox.path}";
extraOptions = [
"sftp.command='ssh -s sftp -p 23 -i ${config.hetznerStorageBox.sshPrivateKeyFile} ${url}'"
];
};
}));
};
}

View file

@ -0,0 +1,12 @@
self: system: let
pkgs = self.pkgs.${system};
in {
type = "app";
drv = pkgs.writeShellApplication {
name = "setup-hetzner-storage-boxes";
text = ''
set -euo pipefail
'';
};
}

Binary file not shown.