docs(3191): the gateway's comments describe a host service, not a container

Prose-only sweep of every remaining claim that nginx or dnsmasq lives
in a container: the port comment (root in a container -> root on the
host), upstreamHost's netns rationale, the ACME state dir, the store
path reachability note, the vhost tree header, dnsmasq's resolv.conf
paragraph (there is no copy and no path unit watching it any more),
the two hive-network bridge comments, and swarm-controller's socket
access-control note, which described a bind-mount that no longer
exists.

No behaviour change; all of it was describing a mechanism that was
deleted.
This commit is contained in:
atlas 2026-08-12 12:20:28 +02:00
commit f85724a638
7 changed files with 54 additions and 59 deletions

View file

@ -33,9 +33,8 @@ in
# gateway_nginx.rs uses this to generate split location
# blocks in agents.conf — static HTML/CSS/JS served from the
# nix store directly; dynamic API paths still proxied to the
# agent daemon. The nix store is shared across nspawn
# containers, so this path is reachable from inside the
# gateway container's nginx.
# agent daemon. nginx runs on the host, which is where this
# store path already is, so it is reachable as written.
HIVE_AGENT_FRONTEND_DIR = "${cfg.servedFrontend}/agent";
# Path to the static runtime asset tree (branding + claude
# prompts). `hive_sh4re::assets::*` reads paths underneath.

View file

@ -26,9 +26,7 @@ let
forgeCfg = config.services.hyperhive.swarm.forge;
networkCfg = config.services.hyperhive.network;
# Dashboard SPA dist, static-served by nginx. Read in OUTER scope so
# `config` is the host's (inside the container block it'd be the
# container's).
# Dashboard SPA dist, static-served by nginx.
dashboardDist = "${config.services.hyperhive.c0re.servedFrontend}/dashboard";
# Full hyperhive-themed Swagger UI dist — nginx serves this whole
@ -243,10 +241,10 @@ in
# mode behind.
chmod 0755 ${builtins.dirOf tlsDir}
chmod 0755 ${tlsDir}
# Copy the host leaf in. `install` writes atomically with the
# target mode; run as root (container root == host root,
# privateUsers=false) so the 0600 root:root host key is
# readable. Key ends up root:nginx 0640 so nginx-pre-start
# Copy the leaf in. `install` writes atomically with the
# target mode; runs as root so the 0600 root:root key written
# by hive-tls-ca is readable. Key ends up root:nginx 0640 so
# nginx-pre-start
# (which runs `nginx -t` as the nginx user, not root) can
# read it — a 0600 root:root key passes the master load but
# fails the pre-start config test with `BIO_new_file() …

View file

@ -1,10 +1,10 @@
# Hive-internal DNS resolver + DHCP, co-located in the gateway
# container — single front-door for both DNS and HTTP, saves a
# sibling container. Listens on the bridge interface from
# Hive-internal DNS resolver + DHCP, running on the host alongside the
# gateway's nginx — single front-door for both DNS and HTTP, and no
# container of its own. Listens on the bridge interface from
# `services.hyperhive.network`; authoritative for the hive domain +
# sub-domains, forwards everything else upstream. Returns the
# `services.dnsmasq` value for the container config (see
# ./default.nix); the DHCP pool bounds are computed by hive-network.
# `services.dnsmasq` value (see ./default.nix); the DHCP pool bounds
# are computed by hive-network.
{
lib,
networkCfg,
@ -68,14 +68,13 @@
dhcp-range = "${networkCfg.dhcpRangeStart},${networkCfg.dhcpRangeEnd},1h";
dhcp-leasefile = "/var/lib/dnsmasq/dnsmasq.leases";
# No explicit upstream: non-hive queries follow dnsmasq's
# resolv.conf default — the gateway container's `/etc/resolv.conf`,
# which nixos-container copies from the host at every start, so the
# hive always uses the host's resolvers. resolvconf is disabled in
# the container (see ./default.nix) so nothing regenerates that
# copy; the host-side `hive-gateway-resolv` path unit (also in
# ./default.nix) pushes in a fresh copy and reloads dnsmasq whenever
# the host's resolvers change, so the copy can't go stale under a
# network switch. Deliberately no fallback `server=`: dnsmasq queries
# resolv.conf default — the host's own `/etc/resolv.conf`, so the
# hive always uses the host's resolvers and follows them live. This
# used to be a *copy* nixos-container made at container start, kept
# fresh by a host-side path unit that pushed in a new one and
# reloaded dnsmasq; running on the host deleted both the copy and
# the machinery that watched it. 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 fill in when the
# host file is empty.

View file

@ -28,10 +28,10 @@ in
example = 8080;
description = ''
TCP port the gateway listens on. Default 80 (canonical web
port). nginx inside the container binds <1024 because the
container's init runs as root; if 80 is already taken on the
host (existing nginx, traefik, etc.) override to an unused
port like 8080 or move the conflicting service.
port). nginx runs on the host as root, so it can bind <1024;
if 80 is already taken on the host (existing nginx, traefik,
etc.) override to an unused port like 8080 or move the
conflicting service.
'';
};
@ -40,8 +40,8 @@ in
default = "127.0.0.1";
description = ''
Host the gateway proxies non-static requests to. Defaults to
`127.0.0.1` because the gateway container shares the host
netns, so loopback resolves directly to hive-c0re.
`127.0.0.1` because nginx runs on the host itself, so loopback
resolves directly to hive-c0re.
'';
};
@ -180,11 +180,11 @@ in
default = false;
example = true;
description = ''
Let nginx inside the gateway container obtain and renew TLS
certificates automatically via ACME (Let's Encrypt). When
enabled, each vhost calls out to Let's Encrypt using the
HTTP-01 challenge on `port` (default 80) and stores certs
inside the gateway container's persistent state dir.
Let the gateway's nginx obtain and renew TLS certificates
automatically via ACME (Let's Encrypt). When enabled, each
vhost calls out to Let's Encrypt using the HTTP-01
challenge on `port` (default 80) and stores certs in the
gateway's persistent state dir on the host.
Requirements:
- `services.hyperhive.domain` must be set and publicly

View file

@ -1,9 +1,9 @@
# nginx virtual-host tree for the gateway container: the `_` default
# server (dashboard, per-agent routing, matrix discovery), the forge
# and matrix sub-domain vhosts, and the Accept-header SPA map for the
# matrix GUI. Pure function — called from ./default.nix inside the
# container config with the outer-scope config values as arguments;
# returns `{ virtualHosts, appendHttpConfig }`.
# nginx virtual-host tree for the gateway: the `_` default server
# (dashboard, per-agent routing, matrix discovery), the forge, matrix
# and authelia sub-domain vhosts, and the Accept-header SPA map for the
# matrix GUI. Pure function — called from ./default.nix with the
# outer-scope config values as arguments; returns
# `{ virtualHosts, appendHttpConfig }`.
{
lib,
cfg, # services.hyperhive.gateway

View file

@ -46,9 +46,8 @@ in
'')
(lib.mkRemovedOptionModule [ "services" "hyperhive" "network" "upstreamDns" ] ''
The hive resolver always follows the host's resolvers now
(dnsmasq reads the gateway container's /etc/resolv.conf, the
host copy made at container start). Configure upstream DNS on
the host itself instead.
(dnsmasq runs on the host and reads its /etc/resolv.conf
directly). Configure upstream DNS on the host itself instead.
'')
];
@ -71,8 +70,8 @@ in
example = "172.30.0.1";
description = ''
IPv4 address assigned to the bridge interface on the host
side. Agents use this address as their DNS server (dnsmasq
in the gateway container binds here). Default `10.42.0.1`
side. Agents use this address as their DNS server (the hive's
dnsmasq binds here). Default `10.42.0.1`
is in RFC 1918 space and unlikely to clash with operator's
existing setup; override if a different range is already in
use.
@ -123,7 +122,7 @@ in
# before broadcast). All containers — agents and service
# containers alike — receive their IPs dynamically from this pool;
# there are no hash-derived static assignments. Consumed by the
# dnsmasq that runs in the gateway container (hive-gateway module).
# hive's dnsmasq (hive-gateway module, host-side).
dhcpRangeStart = lib.mkOption {
type = lib.types.str;
internal = true;
@ -212,7 +211,7 @@ in
# is unconditional now).
networking.bridges.${cfg.bridgeName}.interfaces = [ ];
# Bridge IP — dnsmasq (in the gateway container) binds here.
# Bridge IP — the hive's dnsmasq binds here.
networking.interfaces.${cfg.bridgeName}.ipv4.addresses = [
{
address = cfg.bridgeIp;

View file

@ -4,9 +4,9 @@
# the agents on one host, this owns what is true across hives.
#
# Serves HTTP over a unix socket rather than a TCP port: the gateway's
# nginx is the only intended client, it reaches the socket through a
# bind-mount, and a socket that is never bound to an address cannot be
# reached from off-host by mistake.
# nginx is the only intended client, it runs on this same host and so
# reaches the socket by path, and a socket that is never bound to an
# address cannot be reached from off-host by mistake.
{
pkgs,
lib,
@ -103,13 +103,13 @@ in
the socket itself is `0666` (nginx runs as another user, and
`connect(2)` needs write), exactly as hive-c0re publishes the
per-agent sockets. What keeps that safe is that the directory holds
one socket and is bind-mounted into one container. Moving this path
under a directory that carries anything else `/run/hyperhive`,
which holds the host admin socket, above all hands whatever else
lives there to every consumer that mounts it.
exactly one socket and is traverse-only (`0751`) for everyone else.
Moving this path under a directory that carries anything else
`/run/hyperhive`, which holds the host admin socket, above all
exposes whatever else lives there to the same reachability.
Changing this therefore means re-checking the gateway bind-mount,
not just the daemon.
Changing this therefore means re-checking what else lives in the
new directory, not just the daemon.
'';
};
};
@ -147,9 +147,9 @@ in
# the socket path without being able to list the directory. Same
# shape (and same reason) as hive-c0re's runtime dir.
RuntimeDirectoryMode = "0751";
# Preserved across restarts so the bind-mount source never vanishes
# from under a running gateway container. The daemon unlinks a stale
# socket on start, which is what makes preservation safe.
# Preserved across restarts so the path never vanishes from under a
# running nginx. The daemon unlinks a stale socket on start, which
# is what makes preservation safe.
RuntimeDirectoryPreserve = "yes";
StateDirectory = "swarm-controller";