diff --git a/hosts/12kingdoms-youko/default.nix b/hosts/12kingdoms-youko/default.nix index 0160579f..af84d611 100644 --- a/hosts/12kingdoms-youko/default.nix +++ b/hosts/12kingdoms-youko/default.nix @@ -36,10 +36,41 @@ in repository = "/data/backups/restic/youko"; snapshotSource = "/btr_pool/@persistent"; requiresMountsFor = "/data/backups"; + exclude = [ + # regenerable, huge, or unsuitable for file-level backup + # + # the whole podman storage tree: the image layers are re-pullable, and its + # storage DB is not consistent when copied from a running podman. + # (uptime-kuma uses a named volume under here; its data is not wanted.) + "var/lib/containers" + "var/lib/microvms" + "var/lib/libvirt" + "nfs" + "var/cache" + "var/tmp" + "var/log" + "*.qcow2" + ]; }; modules.btrbk.enable = true; + # The restic REST server the desktops push their backups to. Append-only, so + # a compromised client still cannot delete history; private repos, so each + # client only reaches the repository named after its user. Credentials come + # from agenix; caddy terminates TLS in front of it. + services.restic.server = { + enable = true; + listenAddress = "127.0.0.1:8000"; + dataDir = "/data/backups/rest-server"; + appendOnly = true; + privateRepos = true; + "htpasswd-file" = config.age.secrets."restic-rest-htpasswd".path; + }; + + # repositories live on the HDD, which has to be mounted first + systemd.services.restic-rest-server.unitConfig.RequiresMountsFor = "/data/backups"; + boot.kernelParams = [ # Use transparent huge pages on demand (madvise) instead of a fixed 1G hugetlb # pool (cannot be overcommitted/shared; it stranded memory and blocked diff --git a/hosts/12kingdoms-youko/homelab-services/caddy.nix b/hosts/12kingdoms-youko/homelab-services/caddy.nix index d4f540ee..852f8149 100644 --- a/hosts/12kingdoms-youko/homelab-services/caddy.nix +++ b/hosts/12kingdoms-youko/homelab-services/caddy.nix @@ -63,6 +63,11 @@ in encode zstd gzip reverse_proxy http://localhost:3303 ''; + # the restic REST server the backup clients push to + virtualHosts."backup.writefor.fun".extraConfig = '' + ${hostCommonConfig} + reverse_proxy http://localhost:8000 + ''; virtualHosts."transmission.writefor.fun".extraConfig = '' ${hostCommonConfig} encode zstd gzip diff --git a/vars/networking.nix b/vars/networking.nix index 5b9efd82..667af484 100644 --- a/vars/networking.nix +++ b/vars/networking.nix @@ -187,6 +187,8 @@ rec { # Define the root user's host key for remote builders, so that nix can verify all the remote builders aquamarine.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEOXFhFu9Duzp6ZBE288gDZ6VLrNaeWL4kDrFUh9Neic root@aquamarine"; + # the restic backup server + youko.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEs8b3CmxM+utXZVKvJBssXBupBXvvzjHP40HcY7PSyZ root@youko"; # ruby.publicKey = ""; # kana.publicKey = "";