gateway: fix nginx reload — trigger from host via systemd-run (#889)

The #872 path-unit approach was silently broken: IN_MOVED_TO from an
atomic rename on the host does not propagate across the nspawn
mount-namespace boundary into the container, so the watcher inside
the gateway container never fired.

Fix: after each agents.conf write, c0re calls
`systemd-run --machine=hive-gateway -- nginx -s reload` from the host.
The reload is best-effort (logged on failure, not fatal).

Remove the now-unused `hive-gateway-agents-conf.path` +
`hive-gateway-nginx-reload.service` from the gateway container config.
Update docs/gateway.md + comments to reflect the host-side approach.
This commit is contained in:
atlas 2026-05-31 22:35:06 +02:00 committed by mara
commit 01d7c37af2
3 changed files with 91 additions and 60 deletions

View file

@ -91,21 +91,23 @@ unix-domain socket as each agent opts in. The mechanism:
socket for every sub-agent that hasn't opted in yet. (Legacy name
`.bound` also accepted during the transition window.)
4. **Gateway side**. `gateway_nginx::write` generates
`/var/lib/hyperhive/agents.conf` — a plain nginx include file with
one `location /agent/<name>/` block per agent. UDS upstream
(`http://unix:/run/hive-agent/<name>/web.sock:/`) when
`/var/lib/hyperhive/gateway/agents.conf` — a plain nginx include
file with one `location /agent/<name>/` block per agent. UDS
upstream (`http://unix:/run/hive-agent/<name>/web.sock:/`) when
`hyperhive-socket-bound` marker present; TCP loopback otherwise.
The gateway container bind-mounts `/var/lib/hyperhive/` at
The gateway container bind-mounts `/var/lib/hyperhive/gateway/` at
`/run/hive-state/`; nginx includes `/run/hive-state/agents.conf`.
A systemd path unit (`hive-gateway-agents-conf.path`) inside the
container watches the file and fires `nginx -s reload` on every
atomic rename from c0re — no `nixos-rebuild` needed.
After each write, c0re triggers `nginx -s reload` inside the
gateway container from the HOST via
`systemd-run --machine=hive-gateway nginx -s reload`. This is
intentionally host-side: `IN_MOVED_TO` from an atomic rename does
not propagate across the nspawn mount-namespace boundary, so a
path unit inside the container would never fire (#889).
c0re regenerates `agents.conf` (and fires the path unit → reload) on
two triggers: every topology change (new/removed agents) and every
10s marker poll tick (`agent_sockets::spawn_poll`). `write()` is
idempotent — skips the rename when content is unchanged so the path
unit doesn't fire spuriously.
c0re regenerates `agents.conf` (and triggers a reload) on two
triggers: every topology change (new/removed agents) and every 10s
marker poll tick (`agent_sockets::spawn_poll`). `write()` is
idempotent — skips the rename+reload when content is unchanged.
Transition: agents that haven't flipped `useUnixSocket = true` get a
TCP loopback upstream in `agents.conf` (deterministic port from