diff --git a/hive-c0re/src/gateway_nginx.rs b/hive-c0re/src/gateway_nginx.rs index 0cbf08ff..1087119e 100644 --- a/hive-c0re/src/gateway_nginx.rs +++ b/hive-c0re/src/gateway_nginx.rs @@ -10,7 +10,7 @@ //! switch` needed when agents start, stop, or flip `useUnixSocket`. //! (A path unit inside the container was tried first but `IN_MOVED_TO` //! from the atomic rename does not cross the nspawn mount-namespace -//! boundary — see #889 for the failure analysis.) +//! boundary — see `docs/gateway.md` for the failure analysis.) //! //! Upstream selection mirrors `agent_sockets::build_map`: an agent //! gets a UDS upstream when its `.bound` marker exists (harness has @@ -40,8 +40,7 @@ const HOST_CONF_PATH: &str = "/var/lib/hyperhive/gateway/agents.conf"; /// (not the whole parent dir) at `/run/hive-state/` so nginx inside /// can read it at `/run/hive-state/agents.conf`. Subdirectory scoping /// avoids exposing the rest of `/var/lib/hyperhive/` (which may contain -/// forge tokens or other credentials) to the gateway container (argus 🟡 -/// on #872). +/// forge tokens or other credentials) to the gateway container. #[must_use] pub fn host_conf_path() -> PathBuf { PathBuf::from(HOST_CONF_PATH) @@ -119,7 +118,7 @@ fn render(names: &[String]) -> String { /// inside the container watching the bind-mounted file: `IN_MOVED_TO` /// (fired by the atomic rename) does not reliably propagate across the /// nspawn mount-namespace boundary, so the path-unit approach was -/// silently broken after #872 merged (#889). +/// silently broken (see `docs/gateway.md` for the failure analysis). /// /// The `systemd-run` call is best-effort — a failed reload is logged /// but not fatal. nginx will pick up the new include on its next diff --git a/nix/modules/hive-gateway.nix b/nix/modules/hive-gateway.nix index 20653e71..ef7c5c28 100644 --- a/nix/modules/hive-gateway.nix +++ b/nix/modules/hive-gateway.nix @@ -11,8 +11,8 @@ let forgeCfg = config.services.hyperhive.forge; networkCfg = config.services.hyperhive.network; - # Static error pages for `/agent//` mishaps (#755). Mara's - # call: useful pages instead of nginx's default 404/502 for routes + # Static error pages for `/agent//` mishaps. + # Useful pages of nginx's default 404/502 for routes # we've already special-cased. See `docs/gateway.md::Per-agent # error pages` for the design rationale + page-vs-status semantics. agentErrorPagesDir = pkgs.runCommand "hyperhive-agent-error-pages" { } '' @@ -127,8 +127,8 @@ in default = false; example = true; description = '' - Open `port` in the host firewall. Off by default (#651, - secure-by-default). Flip to `true` to expose the gateway to + Open `port` in the host firewall. Off by default (secure-by-default). + Flip to `true` to expose the gateway to the operator's browser / external clients — required for any out-of-host reach, since the agents themselves talk to hive-c0re via the per-agent unix sockets and don't need the @@ -136,11 +136,9 @@ in proxy (e.g. caddy / traefik on the host) that handles TLS termination + forwards to `port`. - **Breaking change as of #651**: this used to default to - `true`. If you relied on the old default for external reach - (the common case — the gateway is the operator's primary - entry point), add `services.hyperhive.gateway.openFirewall = true;` - to your host config before rebuilding. + **Note**: this used to default to `true`. Add + `services.hyperhive.gateway.openFirewall = true;` to your host + config if external reach stopped working after a recent upgrade. ''; }; @@ -171,7 +169,7 @@ in FluffyChat + several other Matrix clients) hardcodes `https:///.well-known/matrix/client` for homeserver discovery and refuses to fall back to plain http — without - TLS the browser client just won't connect (#837). + TLS the browser client just won't connect. Self-signed means browsers will show a "not secure" warning on first visit; the operator clicks through once per @@ -216,7 +214,7 @@ in # Ensure bind-mount sources exist at host boot before the gateway # container's first start. nspawn would auto-create missing dirs - # (argus 🟡 on #829), but tmpfiles rules make the intent explicit + # tmpfiles rules make the intent explicit # and cover the fresh-boot window before c0re has run. # # /run/hive-agent — per-agent UDS socket dir, written by c0re's @@ -241,7 +239,7 @@ in # layer that matters. privateNetwork = false; # Bind-mount the per-agent socket dir so nginx inside the gateway - # container can `connect(2)` to the UDS upstreams (#784 step 3). + # container can `connect(2)` to the UDS upstreams. # Read-only (we just connect; harness writes the socket inside # the agent's own container). Host-side dir is pre-created by a # tmpfiles rule so nspawn always finds a source at boot. @@ -304,7 +302,7 @@ in # spec compliance) — 443 elides the port. Otherwise fall back # to the plain-http listen with the bare port. See # `docs/gateway.md` ("Self-signed TLS"). Shared at this scope - # (was inlined twice, argus 🟡 on #848). + # Shared to avoid repetition. publicScheme = if cfg.selfSignedTls then "https" else "http"; publicPort = if cfg.selfSignedTls then cfg.httpsPort else cfg.port; publicPortDefault = if cfg.selfSignedTls then 443 else 80; @@ -393,16 +391,16 @@ in # via `systemd-run --machine=hive-gateway nginx -s reload` # after each agents.conf write. A path unit watching the # bind-mounted file inside the container was tried first - # (in #872) but IN_MOVED_TO from an atomic rename on the host + # (A path unit inside the container was tried but IN_MOVED_TO from an atomic rename on the host # does not propagate across the nspawn mount-namespace boundary, - # so the watcher never fired (#889). Host-side trigger is the + # does not cross the mount-namespace boundary. Host-side trigger is the # correct approach. services.nginx = { enable = true; recommendedProxySettings = true; recommendedOptimisation = true; - # Accept-header SPA fallback (#686 / #729): navigations + # Accept-header SPA fallback: navigations # (`Accept: text/html,...`) fall to index.html, asset # fetches (Accept *anything else*) fall to a sentinel # nonexistent path → `try_files` returns 404. Pattern @@ -418,7 +416,7 @@ in listen = vhostListen; locations = # `/matrix/*` → 301 → `matrix./$1` - # (fluffychat moved to sub-domain root in #772; this + # (fluffychat moved to sub-domain root; this # keeps bookmarks + deep-links working during the # transition). See `docs/gateway.md` for the vhost # map. @@ -471,7 +469,7 @@ in } ) // - # `/agent/` catch-all (#755): hits when an operator + # `/agent/` catch-all: hits when an operator # requests `/agent//...`. Without this the # request falls through to `/` (c0re dashboard) and # returns 404 with no useful context. Custom 404 @@ -537,7 +535,7 @@ in }; } // - # Forge sub-domain vhost (#749 / #754). `server_name = + # Forge sub-domain vhost. `server_name = # forge.domain`, proxies all `/` → forgejo. Tuned for # git: `client_max_body_size 1G`, `proxy_read_timeout 1h` # (multi-GB clones). SSH stays direct on `forge.sshPort`. @@ -558,10 +556,10 @@ in }; } // - # Matrix sub-domain vhost (#747 / #764). `server_name = + # Matrix sub-domain vhost. `server_name = # matrixCfg.gatewayHost`. `/_matrix/*` → tuwunel (CORS *, # 50M body cap, 1h long-poll timeout). `/` serves - # fluffychat (#772) or 404 if GUI off. nginx + # fluffychat or 404 if GUI off. nginx # longer-prefix-wins puts `/_matrix/` ahead of `/`. # See `docs/gateway.md`. lib.optionalAttrs (matrixCfg.enable && matrixCfg.gatewayHost != null) { @@ -594,7 +592,7 @@ in // lib.optionalAttrs (hyperhiveDomain != null) { # FluffyChat boot-config pre-fill so the client's # `.well-known/matrix/client` lookup hits the - # right delegation endpoint (#736). + # right delegation endpoint. "= /config.json" = { extraConfig = '' default_type application/json; @@ -612,8 +610,8 @@ in }; }; - # Hive-internal DNS resolver (#805 v1). Co-located in the - # gateway container per mara's call (#805:10957) — single + # Hive-internal DNS resolver, co-located in the + # gateway container — single # front-door for both DNS and HTTP, saves a sibling # container. Listens on the bridge interface from # `services.hyperhive.network`; authoritative for the hive @@ -651,7 +649,7 @@ in # common case where `forge.domain` / # `matrix.gatewayHost` are sub-domains of # `hyperhive.domain` — dnsmasq's `//` rule - # already matches sub-domains (argus 🟡 on #845). + # already matches sub-domains. # Kept explicit because operators can override either # to a cross-domain hostname (e.g. # `forge.domain = "git.example.com"`); listing them diff --git a/nix/modules/hive-network.nix b/nix/modules/hive-network.nix index 18e3356b..e304230b 100644 --- a/nix/modules/hive-network.nix +++ b/nix/modules/hive-network.nix @@ -7,12 +7,10 @@ let cfg = config.services.hyperhive.network; in { - # Hive-internal network — host-side bridge + per-agent DNS resolver - # (#805, prereq for #14 netns isolation). Containers stay on shared - # host netns at v1 — this module just stands the bridge + resolver - # up so the endpoint is in place before #14 flips containers to - # private netns (mara on #805: "we need it before #14 so nothing - # breaks when we switch over"). Full design: docs/network.md. + # Hive-internal network — host-side bridge + per-agent DNS resolver. + # Containers stay on shared host netns at v1; this module stands the + # bridge + resolver up so the endpoint is in place before network + # isolation flips containers to private netns. Full design: docs/network.md. options.services.hyperhive.network = { enable = lib.mkOption {