diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index 90d1a22d..ef3f9e98 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -750,20 +750,37 @@ in HYPERHIVE_SWARM_NAME = config.services.hyperhive.swarmName; } // lib.optionalAttrs config.services.hyperhive.forge.enable { - # In-cluster forge URL — the gateway vhost (`forge.`), which - # nginx proxies to forgejo. Set directly: this env only exists when - # hyperhive is enabled. See `docs/gateway.md::HIVE_FORGE_URL`. - HIVE_FORGE_URL = "http://${config.services.hyperhive.forge.domain}"; + # In-cluster forge URL. + # - Isolated (private netns): containers resolve `forge.` via + # the bridge dnsmasq and reach nginx on port 80. No raw forge port + # needed — nginx proxies to forgejo as it does for the operator. + # - Shared netns: host loopback is reachable, use direct port. + # See `docs/gateway.md::HIVE_FORGE_URL`. + HIVE_FORGE_URL = + if + config.services.hyperhive.network.enable && config.services.hyperhive.network.isolateContainers + then + "http://${config.services.hyperhive.forge.domain}" + else + "http://127.0.0.1:${toString config.services.hyperhive.forge.httpPort}"; } // lib.optionalAttrs config.services.hyperhive.matrix.enable { # In-cluster matrix homeserver URL for each agent's - # hive-matrix-daemon — the gateway vhost (`matrix.`). The + # hive-matrix-daemon. Same shape + rationale as HIVE_FORGE_URL: + # - Isolated (private netns): reach tuwunel via the gateway vhost + # (`matrix.`) on plain http:80 — host loopback is dead. + # - Shared netns: direct host loopback on the tuwunel port. # gatewayHost null-guard falls back to loopback so a domain-less - # config still evals. Forwarded to agents by meta.rs alongside - # HIVE_FORGE_URL; shares the same env-forwarding ordering caveat - # (value baked at config-generation time). + # config doesn't break eval (it just won't work under isolation, + # which needs a gateway anyway). Forwarded to agents by meta.rs + # alongside HIVE_FORGE_URL; shares the same env-forwarding ordering + # caveat (value baked at config-generation time). HIVE_MATRIX_URL = - if config.services.hyperhive.matrix.gatewayHost != null then + if + config.services.hyperhive.network.enable + && config.services.hyperhive.network.isolateContainers + && config.services.hyperhive.matrix.gatewayHost != null + then "http://${config.services.hyperhive.matrix.gatewayHost}" else "http://127.0.0.1:${toString config.services.hyperhive.matrix.httpPort}"; diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index 555b8d4f..ca287a7b 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -377,7 +377,7 @@ in # `environment.etc."resolv.conf".text` is `nameserver `. # This container always shares the host netns # (`privateNetwork = false`), so it reaches `bridgeIp` regardless - # of agent-container isolation. Network module off → inherit the host's + # of `isolateContainers`. Network module off → inherit the host's # resolv.conf. See `docs/network.md`. networking = lib.mkMerge [ (lib.mkIf networkCfg.enable { diff --git a/nix/modules/hive-network.nix b/nix/modules/hive-network.nix index f4a6f9e9..b20e7553 100644 --- a/nix/modules/hive-network.nix +++ b/nix/modules/hive-network.nix @@ -19,18 +19,18 @@ in defaultText = lib.literalExpression "config.services.hyperhive.enable"; example = false; description = '' - **DEPRECATED — ignored.** The hive network (bridge + dnsmasq - resolver + private-netns isolation) is now always on whenever - hyperhive is enabled; setting this to `false` warns and has no - effect. Retained as a no-op so existing configs eval; will be - removed in a future release. - - The network requires `services.hyperhive.domain` to be set — the - dnsmasq resolver is authoritative for `` and its - sub-domains. A bridge interface (`bridgeName`) appears on the host - with `bridgeIp` assigned, the hive-gateway container runs a dnsmasq - on that IP, and each agent container runs in a private netns with a - veth pair on the bridge. + Stand up the hive-internal bridge + dnsmasq resolver. + Defaults to `config.services.hyperhive.enable` so it comes + on automatically with the rest of hyperhive. Requires + `services.hyperhive.domain` to be set — the dnsmasq resolver + is authoritative for `` and its sub-domains. + When enabled: a bridge interface (`bridgeName`) appears on the + host with `bridgeIp` assigned, and the hive-gateway container + runs a dnsmasq listening on that IP for `` + + sub-domains. Agent containers still default to shared host + netns — the endpoint is up but only used once + `isolateContainers = true` flips containers to private netns + + veth peers on this bridge. ''; }; @@ -94,16 +94,11 @@ in isolateContainers = lib.mkOption { type = lib.types.bool; - default = true; + default = false; example = true; description = '' - **DEPRECATED — ignored.** Network isolation is now the only mode and - is always on whenever hyperhive is enabled; the shared-netns path was - removed. This option is retained as a no-op so existing configs eval; - setting it to `false` warns and has no effect. It will be removed in - a future release. - - Each agent container gets a dedicated veth + Flip agent containers from shared host netns to private netns. + When true, each agent container gets a dedicated veth pair attached to `bridgeName` and a deterministic IP from the bridge subnet. The bridge (already up when `enable = true`) becomes the sole routed path between the host and agent @@ -147,27 +142,21 @@ in }; config = lib.mkMerge [ - # The hive network + container isolation are unconditional whenever - # hyperhive is enabled: the shared-netns mode was removed, so there is - # one mode (private netns behind the bridge). `network.enable` and - # `isolateContainers` are kept as deprecated no-op options (see the - # warnings block below) so existing configs that set them still eval. - (lib.mkIf config.services.hyperhive.enable { + (lib.mkIf cfg.enable { assertions = [ { assertion = config.services.hyperhive.domain != null; message = '' - hyperhive requires services.hyperhive.domain to be set — the - hive resolver is authoritative for `` and its - sub-domains, and agents reach the forge/matrix through the - gateway by that domain. Pin a hostname - (`services.hyperhive.domain = "example.com";`). + services.hyperhive.network.enable = true requires + services.hyperhive.domain to be set — the resolver needs a + domain to be authoritative for. Either pin a hostname + (`services.hyperhive.domain = "example.com";`) or set + `services.hyperhive.network.enable = false` explicitly. ''; } ]; - # Virtual bridge — each agent container attaches a veth pair (isolation - # is unconditional now). + # Virtual bridge — veth pairs attach when isolateContainers flips on. networking.bridges.${cfg.bridgeName}.interfaces = [ ]; # Bridge IP — dnsmasq (in the gateway container) binds here. @@ -185,9 +174,23 @@ in }; }) - # Container isolation overlay — now unconditional (the shared-netns - # mode was removed). See docs/network.md#container-isolation. - (lib.mkIf config.services.hyperhive.enable { + # Guard: fires unconditionally on isolateContainers so the assertion + # is not silently swallowed when enable=false. + (lib.mkIf cfg.isolateContainers { + assertions = [ + { + assertion = cfg.enable; + message = '' + services.hyperhive.network.isolateContainers = true requires + services.hyperhive.network.enable = true (the bridge and + resolver must be running before isolation is flipped on). + ''; + } + ]; + }) + + # Container isolation overlay — see docs/network.md#container-isolation. + (lib.mkIf (cfg.enable && cfg.isolateContainers) { # Agents route internet traffic via the bridge; NAT masquerades their RFC-1918 IPs. boot.kernel.sysctl."net.ipv4.ip_forward" = 1; @@ -219,27 +222,5 @@ in HIVE_NETWORK_SUBNET = "${cfg.bridgeIp}/${toString cfg.bridgePrefixLength}"; }; }) - - # Deprecation surface for the removed toggles. Both options are kept so - # existing configs that set them to `true` still eval cleanly; setting - # either to `false` no longer does anything (network + isolation are - # unconditional now), so warn rather than silently ignore. - { - # Only warn when hyperhive itself is enabled — otherwise `cfg.enable` - # defaults to `false` (tracking `hyperhive.enable`) and we'd fire a - # spurious deprecation warning on a host that doesn't run hyperhive. - warnings = lib.optionals config.services.hyperhive.enable ( - lib.optional (!cfg.enable) '' - services.hyperhive.network.enable = false is deprecated and ignored - — the hive network is now always on (private-netns isolation is the - only mode). Remove the setting. - '' - ++ lib.optional (!cfg.isolateContainers) '' - services.hyperhive.network.isolateContainers = false is deprecated - and ignored — network isolation is now the only mode and is always - on. Remove the setting. - '' - ); - } ]; }