diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index c0119b40..ea719720 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -1104,13 +1104,19 @@ in NoNewPrivileges = true; # already runs as unprivileged user PrivateTmp = true; # uses StateDirectory for tmpfiles, not /tmp ProtectHome = true; # HOME = /var/lib/hyperhive; no /home/* access needed - # "full" makes /usr, /etc, /boot read-only. Safe: c0re never - # writes to any of those paths directly — all /etc writes (e.g. - # /etc/nixos-containers) go through hive-priv, and reads from - # /etc/hyperhive/serve.json are read-only. "strict" (everything - # read-only) requires carefully auditing ReadWritePaths for every - # nix store path c0re touches and is deferred to a follow-up. - ProtectSystem = "full"; + # "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: + # - 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. + # - flake.lock ops land in the meta worktree under StateDirectory + # (kept writable by systemd). + # - 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. + ProtectSystem = "strict"; 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