docs(gateway): describe what is, not what changed

Per review: docs represent current state. Every "used to" / "no longer"
clause this branch introduced is gone — including the History section in
network.md, which was a whole subsection about a sync mechanism that
doesn't exist.

Where the removed clause was carrying a real constraint, the constraint
stays and is stated in the present tense instead of as a delta: nothing
narrows what the gateway's nginx can reach except the directory
permissions in front of a socket, and nothing bounds `ReloadGatewayNginx`
except the hard-coded unit name. Those read as rules now rather than as
the story of how they came to be rules.
This commit is contained in:
atlas 2026-08-11 18:09:51 +02:00
commit 98d895cf9e
15 changed files with 77 additions and 146 deletions

View file

@ -124,37 +124,10 @@ There is deliberately no fallback `server=`: dnsmasq queries all known
upstreams in parallel, so a hardcoded public resolver would take a share
of normal traffic, not just cover the gap.
### History: the resolv.conf sync, and why it is gone
Until the gateway moved onto the host, dnsmasq ran in the `hive-gateway`
container and read *that* container's `/etc/resolv.conf` — a one-shot
copy nixos-container made at start. systemd-nspawn(1) is explicit that
nothing propagates into it after early init, because resolv.conf is
normally updated by rename rather than in place. So a host network change
(new router, new lease, laptop moving networks) stranded dnsmasq on a
resolver that no longer answered, and every non-hive lookup from every
agent hung until someone restarted the gateway.
A host-side `hive-gateway-resolv` path unit closed that gap: watch
`/etc/resolv.conf`, `machinectl copy-to` it into the container, reload
dnsmasq. Roughly eighty lines of watcher, marker file, is-active guard
and mid-rewrite-snapshot check — **all of it bridging two copies of one
file.** With one machine there is one file, and the whole unit is
deleted.
🔑 Worth keeping as a shape, not just a story: **the sync was not
complexity anyone chose. It was the cost of a boundary that bought
nothing here** — the gateway already ran with `privateNetwork = false`,
sharing the host's netns, so the container never provided network
isolation in the first place. When a workaround is that elaborate, the
question to ask is what the boundary is *for*.
(Two alternatives were considered at the time and both were worse than
the copy: a path unit *inside* the container never fired, because the
host replaces the file by rename and `IN_MOVED_TO` does not cross the
nspawn mount namespace; and bind-mounting the host's `/etc/resolv.conf`
would have pinned the *first* inode for the container's whole lifetime,
since openresolv writes a temp file and renames over the target.)
dnsmasq runs on the host and reads the host's `/etc/resolv.conf`
directly, so a network change (new router, new lease, laptop moving
networks) reaches it the moment openresolv rewrites the file. There is
nothing to synchronise and no unit watching for it.
`bind-interfaces` + `interface = [ bridgeName "lo" ]` means the
listener only accepts queries from the bridge interface (plus lo for