diff --git a/nix/host-modules/hive-c0re/default.nix b/nix/host-modules/hive-c0re/default.nix index 2cb40eea..fc3086b9 100644 --- a/nix/host-modules/hive-c0re/default.nix +++ b/nix/host-modules/hive-c0re/default.nix @@ -265,9 +265,9 @@ in PrivateTmp = true; # uses StateDirectory for tmpfiles, not /tmp ProtectHome = true; # HOME = /var/lib/hyperhive; no /home/* access needed # "strict" makes the entire filesystem read-only except for - # StateDirectory (/var/lib/hyperhive) and RuntimeDirectory - # (/run/hyperhive), which systemd keeps writable. No - # ReadWritePaths needed beyond the managed directories because: + # StateDirectory (/var/lib/hyperhive), RuntimeDirectory + # (/run/hyperhive), and ReadWritePaths below, which systemd keeps + # writable. Beyond the managed directories: # - nix is invoked directly (lifecycle, meta, flake_check), but # NIX_REMOTE=daemon routes all store writes through the host # daemon — hive-c0re never writes to /nix itself. @@ -276,7 +276,13 @@ in # - nix build worktrees live in PrivateTmp, not /tmp. # - /etc writes (bind-mount edits) go through hive-priv via the # privileged socket; /etc/hyperhive/serve.json is read-only. + # - the gateway's nginx include + htpasswd live under + # /var/lib/hive-gateway/conf, deliberately outside StateDirectory + # (see hive-c0re/src/paths.rs::GATEWAY_CONF_DIR) so nginx never + # needs access to the rest of c0re's state — that separation + # means c0re itself needs an explicit carve-out to write there. ProtectSystem = "strict"; + ReadWritePaths = [ "/var/lib/hive-gateway/conf" ]; ProtectKernelTunables = true; # no sysctl writes ProtectKernelLogs = true; # reads logs via systemd-journal group, not /dev/kmsg ProtectControlGroups = true; # cgroup writes go through hive-priv, not c0re directly