feat(3088): move the gateway's nginx + dnsmasq onto the host
The gateway's nginx + dnsmasq no longer run in their own nspawn container. `nix/host-modules/hive-gateway/default.nix` loses the `containers.hive-gateway` wrapper and everything that existed only to punch holes in it: `privateNetwork = false`, `CAP_NET_ADMIN`, five bind mounts, its own `stateVersion`, `networking.firewall.enable = false`, `networking.resolvconf.enable = false`, and the `hive-gateway-resolv` path+service pair. 465 -> 303 lines. The container never bought isolation here. It shared the host netns by necessity — nginx binds the host's :80/:443, dnsmasq answers on the bridge — so each of those settings was undoing a boundary the gateway could not afford in the first place. Four things made it more than a deletion, none of them visible in the nix diff: - The self-signed cert service also imports the hive CA leaf, so removing it with the container would have left nginx naming a missing cert file, which it refuses to load at all. - The nginx reload is a hive-priv verb. It still needs root, but no longer for the reason its doc gave, and `--machine=` was both transport and scope — so the unit name is now hard-coded in the helper as the containment. - The lifecycle verb named a container that stops existing. - `journalctl -M hive-gateway` had no machine to enter. Per the operator's ruling, the operator verb keeps working and agents lose it. `InfraContainer` answered three questions that used to share an answer; it now splits into `name()` (identity), `target()` (Container vs HostUnit), `service_unit()` (the systemd unit), and `agent_restartable()`, which the MCP restart path checks before the capability so the refusal cannot read as "ask for infra_admin". `SIBLING_CONTAINERS` drops the gateway — it gates the requests that name a container as a string — while `FromStr` still accepts it, because that answers what a name is, not who may act on it. The dashboard's gateway journal reads host journald filtered to `nginx.service`. Prose was corrected where it only named a location, and re-argued where the container was doing security work: a `0666` per-agent socket was safe because only the gateway container had the directory bind-mounted. There is no mount now, so the directory permissions are the whole of the access control — the constraint holds, its mechanism doesn't. Gate: nix fmt / clippy --all-targets -D warnings / cargo test all clean (710 tests); hivectl-cli.md regenerated from the clap tree. The nix eval was run in both TLS shapes at this commit: every delta in the rendered virtualHosts is one of the three intended path moves, dnsmasq settings are byte-identical, and the absence probe flips true -> false with bindMounts emptied.
This commit is contained in:
parent
cae2cf8df6
commit
07852cabc1
34 changed files with 704 additions and 618 deletions
|
|
@ -180,10 +180,12 @@ omitted — agents share the host netns, so there is no per-container net
|
|||
counter (per-agent network needs the netns-isolation roadmap in
|
||||
`docs/network.md`).
|
||||
|
||||
**1NFR4** — start / stop / restart the four hive infrastructure
|
||||
containers (`hive-ci`, `hive-forge`, `hive-gateway`, `hive-matrix`)
|
||||
directly from the dashboard, without needing an `infra_admin` agent's
|
||||
`restart` MCP tool. One row per container: name, a `badge-ok`/`badge-fail`
|
||||
**1NFR4** — start / stop / restart the four hive infrastructure services
|
||||
(`hive-ci`, `hive-forge`, `hive-gateway`, `hive-matrix`) directly from the
|
||||
dashboard, without needing an `infra_admin` agent's `restart` MCP tool.
|
||||
Three are containers; `hive-gateway` is the host's `nginx.service`, and is
|
||||
the one an agent may **not** restart — this panel is the way it gets
|
||||
bounced. One row per service: name, a `badge-ok`/`badge-fail`
|
||||
running/stopped dot, and `↺ R3ST4RT` + `■ ST0P` (running) or `▶ ST4RT`
|
||||
(stopped) buttons, same themed-confirm pattern as the K3PT ST4T3
|
||||
tombstone actions. Backed by
|
||||
|
|
@ -460,7 +462,7 @@ The current capabilities are:
|
|||
| `manage_root_agent` | allows the `set_status` / lifecycle tools on the root agent |
|
||||
| `read_host_journal` | unlocks `get_host_journal` to read journald from inside a container |
|
||||
| `query_agent_state` | allows `get_loose_ends(agent: "<name>")` calls targeting other agents |
|
||||
| `infra_admin` | allows `restart` on hive infrastructure containers (`hive-ci`, `hive-gateway`, `hive-forge`); each restart is logged to the AUDIT trail |
|
||||
| `infra_admin` | allows `restart` on hive infrastructure containers (`hive-ci`, `hive-forge`, `hive-matrix`; the gateway is operator-only); each restart is logged to the AUDIT trail |
|
||||
|
||||
Each row is one agent. Columns are the capability names returned by
|
||||
`GET /api/capabilities` as `caps: Vec<String>`. Checking or unchecking
|
||||
|
|
@ -1340,9 +1342,11 @@ below — some endpoints aren't in it yet.
|
|||
rootfs every ~5 min, `-x` excluding the shared read-only nix store.
|
||||
`null` until the first sample lands.
|
||||
- `POST /api/infra-container/{name}/{action}` — start / stop / restart a
|
||||
hive infra container (C0R3 › 1NFR4 panel). `name` parses into the
|
||||
hive infra service (C0R3 › 1NFR4 panel). `name` parses into the
|
||||
`InfraContainer` allowlist (`hive-ci`/`hive-forge`/`hive-gateway`/
|
||||
`hive-matrix`, 400 on unknown), `action` ∈ `start|stop|restart`. Calls
|
||||
`hive-matrix`, 400 on unknown), and the variant decides the unit —
|
||||
`container@<name>.service`, or `nginx.service` for the gateway.
|
||||
`action` ∈ `start|stop|restart`. Calls
|
||||
the same `priv_client::control_infra_container` helper the
|
||||
`infra_admin` agent path uses; records an `audit_log` entry
|
||||
(`start_infra`/`stop_infra`/`restart_infra`, actor `"operator"`) either
|
||||
|
|
|
|||
Loading…
Reference in a new issue