{
  pkgs,
  lib,
  ...
}: let
  # sops-encrypted secrets (single file holds all service secrets).
  secretsFile = ../../secrets/secrets.yaml;
  # Root-only runtime files restic reads from (0600 root).
  runtimeDir = "/var/lib/restic";
  passwordFile = "/var/lib/restic/.password";
  environmentFile = "/var/lib/restic/environment";
  # Backblaze B2 backend, per restic docs: b2:bucketname.
  repo = "b2:hetzner-severijnse";

  # Materialize the restic password and B2 credentials from sops into
  # root-only files, so secrets are never world-readable in the Nix store.
  writeSecrets = pkgs.writeShellScript "restic-write-secrets" ''
    set -euo pipefail
    mkdir -p ${runtimeDir}
    ${pkgs.sops}/bin/sops \
      --decrypt --extract '["restic_password"]' \
      --input-type yaml --output-type yaml ${secretsFile} \
      | tr -d '\n' > "${passwordFile}"
    chmod 0600 "${passwordFile}"

    : > "${environmentFile}"
    chmod 0600 "${environmentFile}"
    ${pkgs.sops}/bin/sops --decrypt --input-type yaml --output-type yaml ${secretsFile} |
      ${pkgs.gnused}/bin/sed -nE \
        's/^b2_key_id: (.*)/B2_ACCOUNT_ID=\1/p; s/^b2_application_key: (.*)/B2_ACCOUNT_KEY=\1/p' \
        >> "${environmentFile}"
  '';
in {
  systemd.services.restic-password = {
    description = "Materialize restic repository password and B2 credentials from sops";
    wantedBy = ["multi-user.target"];
    # The age key lives in /etc/age/keys.txt; the service must know where it is
    # and needs a HOME for age to report its user config directory.
    environment.SOPS_AGE_KEY_FILE = "/etc/age/keys.txt";
    serviceConfig = {
      Type = "oneshot";
      Environment = ["HOME=/root"];
      ExecStart = "${writeSecrets}";
    };
  };

  # B2 credentials are supplied via environmentFile (B2_ACCOUNT_ID / B2_ACCOUNT_KEY),
  # matching the official module example which combines `repository` and `environmentFile`.
  services.restic.backups.localbackup = {
    repository = "b2:hetzner-severijnse";
    environmentFile = environmentFile;
    passwordFile = passwordFile;
    initialize = true;
    paths = [
      "/home/admin"
      "/var/lib/postgresql"
      "/var/lib/gitea"
      "/var/lib/caddy"
      "/var/lib/virtualcam"
      "/var/lib/stalwart"
      "/var/lib/bulwark"
      "/var/lib/coredns"
      "/etc/nixos"
    ];
    exclude = [
      "/home/admin/backups"
      "/home/admin/.opencode"
      "/home/admin/.local"
      "/home/admin/.npm"
      "/home/admin/.config"
      "*.log"
      "*.log.*"
      "**/.cache"
    ];
    timerConfig = {
      OnCalendar = "Mon *-*-* 03:00:00";
      Persistent = true;
      RandomizedDelaySec = "15m";
    };
    pruneOpts = [
      "--keep-daily 7"
      "--keep-weekly 4"
      "--keep-monthly 6"
    ];
    runCheck = true;
  };

  # The backup must never run before the secrets exist.
  systemd.services."restic-backups-localbackup" = {
    requires = ["restic-password.service"];
    after = ["restic-password.service"];
  };
}
