Compare commits

..
5 changed files with 45 additions and 44 deletions

View file

@ -17,9 +17,10 @@ Same shape as [`gateway.md::hive-forge container shape`](gateway.md):
operator already runs on the host — separate systemd namespace, operator already runs on the host — separate systemd namespace,
separate state dir. separate state dir.
- Container shares the host network namespace - Container shares the host network namespace
(`privateNetwork = false`) for state + systemd-unit isolation. Agents (`privateNetwork = false`) so agents reach tuwunel at
reach the homeserver at `matrix.<domain>` via the gateway (agents `http://localhost:<httpPort>` without extra plumbing — the
run in private netns and can't access host loopback directly). nixos-container is here for state + systemd-unit isolation, not
network isolation.
- Persistent state at - Persistent state at
`/var/lib/nixos-containers/hive-matrix/var/lib/matrix-tuwunel/` `/var/lib/nixos-containers/hive-matrix/var/lib/matrix-tuwunel/`
survives container restart / host reboot. To wipe, destroy the survives container restart / host reboot. To wipe, destroy the
@ -51,9 +52,9 @@ sub-domain from the user-facing identifier.
## Default-closed firewall ## Default-closed firewall
`openFirewall` defaults to `false` (secure-by-default): the host `openFirewall` defaults to `false` (secure-by-default): the
reaches the homeserver on loopback, and agent containers reach it homeserver is reachable from the host + every agent container via
at `matrix.<domain>` via the gateway — so the firewall hole only loopback either way (shared netns), so the firewall hole only
matters for access from *outside* the host. Flip to `true` when matters for access from *outside* the host. Flip to `true` when
announcing the homeserver to other hives or when an external matrix announcing the homeserver to other hives or when an external matrix
client needs to reach the client-server API directly. client needs to reach the client-server API directly.

View file

@ -462,11 +462,11 @@ Validated: must be an `http://` or `https://` URL or the empty string.
**`hyperhive.matrix.url`** — homeserver URL used by **`hyperhive.matrix.url`** — homeserver URL used by
`hive-matrix-daemon` when connecting via the matrix-sdk. Default `hive-matrix-daemon` when connecting via the matrix-sdk. Default
(`localhost:8008`) is overridden by hive-c0re at deploy time to the points at the in-host tuwunel (`localhost:8008`), reachable over the
gateway-routed `matrix.<domain>` URL so isolated agents can reach the host loopback in shared-netns mode. Override per-agent when an agent
homeserver. Override per-agent when an agent should talk to a should talk to a different homeserver — for example a remote hive's
different homeserver — for example a remote hive's tuwunel reached tuwunel reached over a VPN, or an external Matrix server for a
over a VPN, or an external Matrix server for a federation-only agent. federation-only agent.
### Claude Code plugins ### Claude Code plugins

View file

@ -56,8 +56,8 @@ let
in in
{ {
# Private Forgejo in a `hive-forge` nixos-container, shared host # Private Forgejo in a `hive-forge` nixos-container, shared host
# netns. Agents reach it at `forge.<domain>` via the gateway. State # netns so agents reach it on loopback. State at
# at `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives # `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives
# restart. See `docs/gateway.md::hive-forge container shape`. # restart. See `docs/gateway.md::hive-forge container shape`.
# The internal forge is mandatory — it's the canonical store for the # The internal forge is mandatory — it's the canonical store for the
@ -182,12 +182,13 @@ in
example = true; example = true;
description = '' description = ''
Open `httpPort` + `sshPort` in the host firewall. Off by Open `httpPort` + `sshPort` in the host firewall. Off by
default (secure-by-default): agent containers reach the forge default (secure-by-default): the forge is reachable from the
at `forge.<domain>` via the gateway (not directly), and the host + every agent container via `localhost` either way
host reaches it on loopback so the firewall opens only (shared netns), so the firewall opens only matter for access
matter for access from outside the host. Flip to `true` when from outside the host. Flip to `true` when you want the
you want the operator's browser or external git clients to operator's browser / external git clients to hit the forge
hit the forge directly. directly. (The container shares host netns, so this is the
only firewall layer that matters.)
**Breaking change**: this used to default to `true`. If you **Breaking change**: this used to default to `true`. If you
relied on the old default for external reach, add relied on the old default for external reach, add

View file

@ -173,12 +173,12 @@ in
example = true; example = true;
description = '' description = ''
Open `httpPort` in the host firewall. Off by default Open `httpPort` in the host firewall. Off by default
(secure-by-default): the host reaches the homeserver on (secure-by-default): the homeserver is reachable from the
loopback, and agent containers reach it at `matrix.<domain>` host + every agent container via `localhost` either way
via the gateway so the firewall open only matters for (shared netns), so the firewall open only matters for access
access from outside the host. Flip to `true` when announcing from outside the host. Flip to `true` when announcing the
the homeserver to other hives or when an external matrix homeserver to other hives or when an external matrix client
client needs to reach the client-server API directly. needs to reach the client-server API directly.
**Breaking change**: this used to default to `true`. If you **Breaking change**: this used to default to `true`. If you
relied on the old default for external reach, add relied on the old default for external reach, add

View file

@ -510,12 +510,10 @@ in
example = "https://matrix.darkest.space"; example = "https://matrix.darkest.space";
description = '' description = ''
Matrix homeserver URL the agent's `hive-matrix-daemon` connects Matrix homeserver URL the agent's `hive-matrix-daemon` connects
to. At runtime hive-c0re forwards the isolation-aware URL to. Default points at the in-host tuwunel (shared netns).
(`matrix.<domain>` via the gateway) so isolated agents reach Override per-agent when an agent should talk to an external
the homeserver without crossing host loopback. Override homeserver instead (e.g. a federation-only setup or a remote
per-agent when an agent should talk to an external homeserver hive's tuwunel reached via a vpn).
instead (e.g. a federation-only setup or a remote hive's
tuwunel reached via a vpn).
''; '';
}; };
@ -1518,7 +1516,8 @@ in
# for the hive's own zones, so `forge.<domain>` stops resolving. We # for the hive's own zones, so `forge.<domain>` stops resolving. We
# disable resolvconf and tell dhcpcd not to touch resolv.conf (without # disable resolvconf and tell dhcpcd not to touch resolv.conf (without
# disabling dhcpcd itself, so the veth still gets its address); then # disabling dhcpcd itself, so the veth still gets its address); then
# the hyperhive-isolated-dns oneshot owns resolv.conf. (Same "take # whoever wrote resolv.conf last owns it: the nixos-container host-copy
# in shared netns, or the oneshot in isolated mode. (Same "take
# resolvconf out of the loop" approach the matrix container uses.) # resolvconf out of the loop" approach the matrix container uses.)
networking.resolvconf.enable = false; networking.resolvconf.enable = false;
networking.dhcpcd.extraConfig = "nohook resolv.conf"; networking.dhcpcd.extraConfig = "nohook resolv.conf";
@ -1529,11 +1528,11 @@ in
# 127.0.0.53) is unreachable from a private netns and isn't # 127.0.0.53) is unreachable from a private netns and isn't
# authoritative for the hive's own zones (forge.<domain> etc.). The # authoritative for the hive's own zones (forge.<domain> etc.). The
# bridge dnsmasq (gateway IP) is. hive-priv drops the marker # bridge dnsmasq (gateway IP) is. hive-priv drops the marker
# `/etc/hyperhive-bridge-dns` (containing the gateway IP) since # `/etc/hyperhive-bridge-dns` (containing the gateway IP) only when
# isolation is always on; the oneshot reads it and rewrites # isolation is on, so this oneshot is inert in shared-netns mode — the
# resolv.conf on every boot. Ordered before the first DNS consumer # same shared container toplevel does the right thing in both modes.
# (tea-login) and the network targets so name resolution works for # Ordered before the first DNS consumer (tea-login) and the network
# the very first turn. # targets so name resolution works for the very first turn.
systemd.services.hyperhive-isolated-dns = { systemd.services.hyperhive-isolated-dns = {
description = "point resolv.conf at the hive bridge resolver (isolated containers)"; description = "point resolv.conf at the hive bridge resolver (isolated containers)";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -1730,13 +1729,13 @@ in
RUST_LOG = "info"; RUST_LOG = "info";
} }
# Homeserver URL: by default the daemon inherits the host-forwarded # Homeserver URL: by default the daemon inherits the host-forwarded
# HIVE_MATRIX_URL (set by hive-c0re to `matrix.<domain>` via the # HIVE_MATRIX_URL (set isolation-aware by hive-c0re: `matrix.<domain>`
# gateway, since agents run in private netns and can't reach host # via the gateway under private-netns isolation, loopback otherwise),
# loopback directly), falling back to the daemon's built-in # falling back to the daemon's built-in localhost default if the
# localhost default if the forward is absent. A per-agent # forward is absent. A per-agent `hyperhive.matrix.url` override
# `hyperhive.matrix.url` override (non-default) is set unit-level # (non-default) is set unit-level so it wins over the forwarded value;
# so it wins over the forwarded value; at the default we # at the default we deliberately DON'T set it so the forwarded
# deliberately DON'T set it so the forwarded value isn't shadowed. # isolation-aware value isn't shadowed.
// lib.optionalAttrs (config.hyperhive.matrix.url != matrixUrlDefault) { // lib.optionalAttrs (config.hyperhive.matrix.url != matrixUrlDefault) {
HIVE_MATRIX_URL = config.hyperhive.matrix.url; HIVE_MATRIX_URL = config.hyperhive.matrix.url;
} }