diff --git a/.github/instructions/soteria-host.instructions.md b/.github/instructions/soteria-host.instructions.md index b1aa9fe..8628e65 100644 --- a/.github/instructions/soteria-host.instructions.md +++ b/.github/instructions/soteria-host.instructions.md @@ -21,6 +21,7 @@ When editing `modules/hosts/soteria/default.nix`, preserve this composition unle - Import `nixos.step-ssh-host` to enable host SSH cert integration. - Import `nixos.janus-ca` so Step client trust material and defaults remain available. +- Import `nixos.restic-server` so the RESTic REST server implementation lives in the shared module rather than inline host wiring. - Keep `step-ssh-host.hostname = hostname;` so cert principals match host naming. ## SSH Cert Mechanics On Soteria @@ -65,31 +66,38 @@ Current implementation note: ## Restic REST Server On Soteria -Soteria's RESTic REST server is defined directly in the host module, not through the shared `nixos.restic-server` helper. Trace it this way: +Soteria's RESTic REST server is implemented by the shared `nixos.restic-server` module and configured by host-local `resticServer` values. Trace it this way: -1. `modules/hosts/soteria/default.nix` configures `services.restic.server` inline with: +1. `modules/hosts/soteria/default.nix` imports `nixos.restic-server` and configures the host-local `resticServer` option set with: - `enable = true` + - `dataDir = "/mnt/restic"` - `privateRepos = true` - `listenAddress = "0.0.0.0:8000"` - - `extraFlags = [ "--no-auth" "--tls" "--tls-cert=${config.mtls.certFile}" "--tls-key=${config.mtls.keyFile}" ]` -2. The host opens the matching TCP port separately via `networking.firewall.allowedTCPPorts = [ 8000 ]`. -3. TLS for the REST server is provided by the same mTLS certificate/key files used elsewhere on the host: - - `--tls-cert=${config.mtls.certFile}` - - `--tls-key=${config.mtls.keyFile}` -4. The mTLS renewal hook includes `restic-rest-server.service` in `mtls.renew.reloadUnits`, so certificate rotation reloads the REST server alongside Forgejo. -5. `loginText.extraServiceStatus` exposes the running unit as `restic-rest-server.service`, which is the service name to keep in mind for status and reload behavior. + - `tls.certFile = config.mtls.certFile` + - `tls.keyFile = config.mtls.keyFile` +2. `modules/features/restic.nix` maps those `resticServer` options into `services.restic.server` and appends TLS flags when both TLS paths are set. +3. The shared module keeps the server base behavior in one place: + - `services.restic.server.enable = true` + - `services.restic.server.dataDir = cfg.dataDir` + - `services.restic.server.listenAddress = cfg.listenAddress` + - `services.restic.server.privateRepos = cfg.privateRepos` + - `services.restic.server.extraFlags = cfg.extraFlags ++ tlsFlags` +4. `modules/features/restic.nix` also opens the matching TCP port through `networking.firewall.allowedTCPPorts`, deriving it from `resticServer.listenAddress`. +5. The mTLS renewal hook includes `restic-rest-server.service` in `mtls.renew.reloadUnits`, so certificate rotation reloads the REST server alongside Forgejo. +6. `loginText.extraServiceStatus` exposes the running unit as `restic-rest-server.service`, which is the service name to keep in mind for status and reload behavior. ### Storage Location -- Soteria does not set `services.restic.server.dataDir` in its host definition. -- Because Soteria does not import `nixos.restic-server`, it also does not inherit the repo helper's `/mnt/restic` override from `modules/features/restic.nix`. -- That means repository storage follows the underlying NixOS `services.restic.server` default data directory unless the host explicitly sets `dataDir` later. +- Soteria explicitly sets `resticServer.dataDir = "/mnt/restic"`. +- The shared module maps that value into `services.restic.server.dataDir`, so `/mnt/restic` is now the intended repository storage location for this host. +- The shared module also derives the firewall port from `resticServer.listenAddress`, so Soteria no longer needs a separate `networking.firewall.allowedTCPPorts = [ 8000 ]` line. +- If storage needs to move later, change the `resticServer.dataDir` input or the shared module contract, not ad hoc service cleanup logic. - `privateRepos = true` constrains repo exposure behavior, but it does not define storage location by itself. Current implementation note: - The REST server is TLS-protected but currently passed `--no-auth`, so client access control relies on transport/security model rather than rest-server password auth. -- If you want Soteria to use `/mnt/restic`, either set `services.restic.server.dataDir = "/mnt/restic"` in the host or switch to the shared `nixos.restic-server` module and then reconcile port/TLS differences. +- The shared module default listen address is not Soteria's deployed value; Soteria deliberately overrides it to `0.0.0.0:8000` in the host. ## Forgejo Implementation On Soteria