From 9067398e3ccd72d0ca5f27036ca31e55645038e3 Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 4 Jul 2026 21:06:24 +0200 Subject: [PATCH 1/4] chore(docs,nix): remove stale shared-netns references from matrix URL docs Agents run in private netns (always-on isolation) and can't reach host loopback directly. hive-c0re forwards HIVE_MATRIX_URL set to `matrix.` via the gateway. Update two places that still referenced the removed shared-netns path. --- docs/turn-loop.md | 10 +++++----- nix/templates/harness-base.nix | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/turn-loop.md b/docs/turn-loop.md index d6e987b7..75cef004 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -462,11 +462,11 @@ Validated: must be an `http://` or `https://` URL or the empty string. **`hyperhive.matrix.url`** — homeserver URL used by `hive-matrix-daemon` when connecting via the matrix-sdk. Default -points at the in-host tuwunel (`localhost:8008`), reachable over the -host loopback in shared-netns mode. Override per-agent when an agent -should talk to a different homeserver — for example a remote hive's -tuwunel reached over a VPN, or an external Matrix server for a -federation-only agent. +(`localhost:8008`) is overridden by hive-c0re at deploy time to the +gateway-routed `matrix.` URL so isolated agents can reach the +homeserver. Override per-agent when an agent should talk to a +different homeserver — for example a remote hive's tuwunel reached +over a VPN, or an external Matrix server for a federation-only agent. ### Claude Code plugins diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index 1610fa6f..dbe0536f 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -1729,13 +1729,13 @@ in RUST_LOG = "info"; } # Homeserver URL: by default the daemon inherits the host-forwarded - # HIVE_MATRIX_URL (set isolation-aware by hive-c0re: `matrix.` - # via the gateway under private-netns isolation, loopback otherwise), - # falling back to the daemon's built-in localhost default if the - # forward is absent. A per-agent `hyperhive.matrix.url` override - # (non-default) is set unit-level so it wins over the forwarded value; - # at the default we deliberately DON'T set it so the forwarded - # isolation-aware value isn't shadowed. + # HIVE_MATRIX_URL (set by hive-c0re to `matrix.` via the + # gateway, since agents run in private netns and can't reach host + # loopback directly), falling back to the daemon's built-in + # localhost default if the forward is absent. A per-agent + # `hyperhive.matrix.url` override (non-default) is set unit-level + # so it wins over the forwarded value; at the default we + # deliberately DON'T set it so the forwarded value isn't shadowed. // lib.optionalAttrs (config.hyperhive.matrix.url != matrixUrlDefault) { HIVE_MATRIX_URL = config.hyperhive.matrix.url; } From 03e07c7d3775aa2edc94a36428617bb191cbd980 Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 4 Jul 2026 21:08:09 +0200 Subject: [PATCH 2/4] chore(nix): fix remaining stale shared-netns references in harness-base.nix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Option doc: 'Default points at the in-host tuwunel (shared netns)' → updated to reflect that c0re forwards the gateway URL at runtime - DNS oneshot comment: 'inert in shared-netns mode' → removed since isolation is always on; oneshot always runs --- nix/templates/harness-base.nix | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index dbe0536f..6fadb368 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -510,10 +510,12 @@ in example = "https://matrix.darkest.space"; description = '' Matrix homeserver URL the agent's `hive-matrix-daemon` connects - to. Default points at the in-host tuwunel (shared netns). - Override per-agent when an agent should talk to an external - homeserver instead (e.g. a federation-only setup or a remote - hive's tuwunel reached via a vpn). + to. At runtime hive-c0re forwards the isolation-aware URL + (`matrix.` via the gateway) so isolated agents reach + the homeserver without crossing host loopback. Override + per-agent when an agent should talk to an external homeserver + instead (e.g. a federation-only setup or a remote hive's + tuwunel reached via a vpn). ''; }; @@ -1516,8 +1518,7 @@ in # for the hive's own zones, so `forge.` stops resolving. We # disable resolvconf and tell dhcpcd not to touch resolv.conf (without # disabling dhcpcd itself, so the veth still gets its address); then - # whoever wrote resolv.conf last owns it: the nixos-container host-copy - # in shared netns, or the oneshot in isolated mode. (Same "take + # the hyperhive-isolated-dns oneshot owns resolv.conf. (Same "take # resolvconf out of the loop" approach the matrix container uses.) networking.resolvconf.enable = false; networking.dhcpcd.extraConfig = "nohook resolv.conf"; @@ -1528,11 +1529,11 @@ in # 127.0.0.53) is unreachable from a private netns and isn't # authoritative for the hive's own zones (forge. etc.). The # bridge dnsmasq (gateway IP) is. hive-priv drops the marker - # `/etc/hyperhive-bridge-dns` (containing the gateway IP) only when - # isolation is on, so this oneshot is inert in shared-netns mode — the - # same shared container toplevel does the right thing in both modes. - # Ordered before the first DNS consumer (tea-login) and the network - # targets so name resolution works for the very first turn. + # `/etc/hyperhive-bridge-dns` (containing the gateway IP) since + # isolation is always on; the oneshot reads it and rewrites + # resolv.conf on every boot. Ordered before the first DNS consumer + # (tea-login) and the network targets so name resolution works for + # the very first turn. systemd.services.hyperhive-isolated-dns = { description = "point resolv.conf at the hive bridge resolver (isolated containers)"; wantedBy = [ "multi-user.target" ]; From d7bed0052c78cec4ed72d516d397be69d859698f Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 4 Jul 2026 21:09:06 +0200 Subject: [PATCH 3/4] chore(nix): fix stale 'localhost via shared netns' claim in forge openFirewall doc Agents in private netns reach the forge at forge. via the gateway, not via localhost directly. The conclusion (firewall only matters for external access) is correct; the mechanism description was stale from the pre-isolation era. --- nix/modules/hive-forge.nix | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/nix/modules/hive-forge.nix b/nix/modules/hive-forge.nix index c59e4d9a..bea00e7a 100644 --- a/nix/modules/hive-forge.nix +++ b/nix/modules/hive-forge.nix @@ -182,13 +182,12 @@ in example = true; description = '' Open `httpPort` + `sshPort` in the host firewall. Off by - default (secure-by-default): the forge is reachable from the - host + every agent container via `localhost` either way - (shared netns), so the firewall opens only matter for access - from outside the host. Flip to `true` when you want the - operator's browser / external git clients to hit the forge - directly. (The container shares host netns, so this is the - only firewall layer that matters.) + default (secure-by-default): agent containers reach the forge + at `forge.` via the gateway (not directly), and the + host reaches it on loopback — so the firewall opens only + matter for access from outside the host. Flip to `true` when + you want the operator's browser or external git clients to + hit the forge directly. **Breaking change**: this used to default to `true`. If you relied on the old default for external reach, add From 23f13d9e71e859eba44b65b37d045f9ed2503bb6 Mon Sep 17 00:00:00 2001 From: atlas Date: Sat, 4 Jul 2026 21:10:47 +0200 Subject: [PATCH 4/4] chore(docs,nix): fix stale 'localhost via shared netns' claims in forge/matrix Agents in private netns can't reach host loopback directly; they use forge. and matrix. via the gateway. Update four locations that still claimed direct loopback access: - hive-forge.nix: module header + openFirewall description - hive-matrix.nix: openFirewall description - docs/matrix.md: container design bullet + openFirewall section --- docs/matrix.md | 13 ++++++------- nix/modules/hive-forge.nix | 4 ++-- nix/modules/hive-matrix.nix | 12 ++++++------ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/matrix.md b/docs/matrix.md index 7e3dd972..65c89276 100644 --- a/docs/matrix.md +++ b/docs/matrix.md @@ -17,10 +17,9 @@ Same shape as [`gateway.md::hive-forge container shape`](gateway.md): operator already runs on the host — separate systemd namespace, separate state dir. - Container shares the host network namespace - (`privateNetwork = false`) so agents reach tuwunel at - `http://localhost:` without extra plumbing — the - nixos-container is here for state + systemd-unit isolation, not - network isolation. + (`privateNetwork = false`) for state + systemd-unit isolation. Agents + reach the homeserver at `matrix.` via the gateway (agents + run in private netns and can't access host loopback directly). - Persistent state at `/var/lib/nixos-containers/hive-matrix/var/lib/matrix-tuwunel/` survives container restart / host reboot. To wipe, destroy the @@ -52,9 +51,9 @@ sub-domain from the user-facing identifier. ## Default-closed firewall -`openFirewall` defaults to `false` (secure-by-default): the -homeserver is reachable from the host + every agent container via -loopback either way (shared netns), so the firewall hole only +`openFirewall` defaults to `false` (secure-by-default): the host +reaches the homeserver on loopback, and agent containers reach it +at `matrix.` via the gateway — so the firewall hole only matters for access from *outside* the host. Flip to `true` when announcing the homeserver to other hives or when an external matrix client needs to reach the client-server API directly. diff --git a/nix/modules/hive-forge.nix b/nix/modules/hive-forge.nix index bea00e7a..8178e196 100644 --- a/nix/modules/hive-forge.nix +++ b/nix/modules/hive-forge.nix @@ -56,8 +56,8 @@ let in { # Private Forgejo in a `hive-forge` nixos-container, shared host - # netns so agents reach it on loopback. State at - # `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives + # netns. Agents reach it at `forge.` via the gateway. State + # at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives # restart. See `docs/gateway.md::hive-forge container shape`. # The internal forge is mandatory — it's the canonical store for the diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index ed120fac..b8a7378a 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -173,12 +173,12 @@ in example = true; description = '' Open `httpPort` in the host firewall. Off by default - (secure-by-default): the homeserver is reachable from the - host + every agent container via `localhost` either way - (shared netns), so the firewall open only matters for access - from outside the host. Flip to `true` when announcing the - homeserver to other hives or when an external matrix client - needs to reach the client-server API directly. + (secure-by-default): the host reaches the homeserver on + loopback, and agent containers reach it at `matrix.` + via the gateway — so the firewall open only matters for + access from outside the host. Flip to `true` when announcing + the homeserver to other hives or when an external matrix + client needs to reach the client-server API directly. **Breaking change**: this used to default to `true`. If you relied on the old default for external reach, add