diff --git a/nix/modules/hive-ci.nix b/nix/modules/hive-ci.nix index 96ddebdb..986d468b 100644 --- a/nix/modules/hive-ci.nix +++ b/nix/modules/hive-ci.nix @@ -11,6 +11,19 @@ let networkCfg = config.services.hyperhive.network; tlsCfg = config.services.hyperhive.tls; + # Static bridge address for the hive-ci container. The hive bridge has + # NO DHCP server: agent containers get deterministic static IPs + # (`lifecycle::agent_network_ip` hashes each name across .2..broadcast-1) + # and dnsmasq on the bridge is DNS-only. hive-ci is the one service + # container on the bridge, so it needs a static address too — `useDHCP` + # here only hangs the boot waiting for a lease nothing serves. Reserve the + # top host address of the (default /24) subnet; a clash with an agent that + # happens to hash here is the same rename-to-resolve case as any + # agent/agent IP collision. Operators on a non-/24 bridge (or with + # `bridgeIp` set to the top address) should pick a free host address. + ciBridgeOctets = lib.splitString "." networkCfg.bridgeIp; + ciBridgeIp = "${lib.elemAt ciBridgeOctets 0}.${lib.elemAt ciBridgeOctets 1}.${lib.elemAt ciBridgeOctets 2}.254"; + # Self-signed TLS is the gateway default (no operator cert / ACME). When # active, forgejo's ROOT_URL is `https://forge.` and the leaf is # signed by the host hive CA — so the runner's Node-based actions (e.g. @@ -410,14 +423,21 @@ in # affect traffic destined for the bridge IP itself. networking.nameservers = [ networkCfg.bridgeIp ]; # With privateNetwork=true + hostBridge the container's veth - # is bridge-attached. Enable DHCP on eth0 so the container gets - # an IP from dnsmasq on the bridge (hive-gateway serves the - # bridge subnet). Per-interface rather than global: nixos-containers - # sets networking.useDHCP = false for all containers (to silence - # the deprecated global DHCP warning), so setting useDHCP = true - # globally would conflict. eth0 is the inner veth name assigned - # by systemd-nspawn when hostBridge is used. - networking.interfaces.eth0.useDHCP = true; + # (eth0) is bridge-attached. There is no DHCP server on the hive + # bridge (dnsmasq is DNS-only; agents use static IPs), so assign a + # static address + default route via the bridge gateway rather than + # DHCP — `useDHCP` here just hangs boot on a lease that never + # arrives. See `ciBridgeIp` above. + networking.interfaces.eth0.ipv4.addresses = [ + { + address = ciBridgeIp; + prefixLength = networkCfg.bridgePrefixLength; + } + ]; + networking.defaultGateway = { + address = networkCfg.bridgeIp; + interface = "eth0"; + }; # nspawn containers can't create user-namespaces, so nix # sandboxing always fails. Fall back to unsandboxed builds.