diff --git a/docs/network.md b/docs/network.md index e0c6056b..30811770 100644 --- a/docs/network.md +++ b/docs/network.md @@ -26,7 +26,6 @@ listener on `bridgeIp` is on the host's bridge interface. enable = true; domain = "darkest.space"; # network.bridgeIp = "10.42.0.1"; # default - # network.upstreamDns = [ "1.1.1.1" "9.9.9.9" ]; # default }; } ``` @@ -48,9 +47,12 @@ schemes pick their own. dnsmasq is **authoritative** for the hive's own zones — answers ``, `forge.`, `matrix.` queries with the bridge IP (where nginx is reachable). Everything -else gets forwarded to `upstreamDns`. Containers don't need to know -the upstream — they query the bridge IP and dnsmasq does the right -thing per-name. +else is forwarded to the host's own resolvers: dnsmasq reads the +gateway container's `/etc/resolv.conf`, the host copy nixos-container +makes at each container start — a host resolver change is picked up +on the next gateway restart. Containers don't need to know the +upstream — they query the bridge IP and dnsmasq does the right thing +per-name. `bind-interfaces` + `interface = [ bridgeName "lo" ]` means the listener only accepts queries from the bridge interface (plus lo for diff --git a/nix/host-modules/hive-gateway/default.nix b/nix/host-modules/hive-gateway/default.nix index acdd34e7..24555a1f 100644 --- a/nix/host-modules/hive-gateway/default.nix +++ b/nix/host-modules/hive-gateway/default.nix @@ -163,6 +163,16 @@ in { system.stateVersion = "26.05"; + # Keep the host-copied /etc/resolv.conf intact. nixos-container + # copies the host's file in at every container start, but + # resolvconf's host-tracking mode then regenerates it — to an + # empty file, since the host file doesn't cross the boundary + # after start (the same failure the matrix container hit). + # With resolvconf off, nothing touches the copy: nginx's own + # lookups (ACME) and dnsmasq's follow-the-host upstream + # default (see ./dnsmasq.nix) both read the host's resolvers. + networking.resolvconf.enable = false; + # ACME (Let's Encrypt) integration. nginx vhosts set # `enableACME = true` via the vhost builder; this provides the # shared ACME config (acceptTerms + email). The gateway diff --git a/nix/host-modules/hive-gateway/dnsmasq.nix b/nix/host-modules/hive-gateway/dnsmasq.nix index 41361df4..6852df5a 100644 --- a/nix/host-modules/hive-gateway/dnsmasq.nix +++ b/nix/host-modules/hive-gateway/dnsmasq.nix @@ -27,10 +27,6 @@ ]; bind-interfaces = true; port = 53; - # Don't read /etc/resolv.conf — we control upstream explicitly to - # dodge dependency on the gateway container's own resolver state. - no-resolv = true; - server = networkCfg.upstreamDns; # Hive authoritative records — answer queries for the hive domain # + its sub-domains with the bridge IP, where nginx is reachable # from every container netns. @@ -55,5 +51,11 @@ # containers such as hive-ci) receive their IPs dynamically. dhcp-range = "${networkCfg.dhcpRangeStart},${networkCfg.dhcpRangeEnd},1h"; dhcp-leasefile = "/var/lib/dnsmasq/dnsmasq.leases"; + # No explicit upstream: non-hive queries follow dnsmasq's + # resolv.conf default — the gateway container's `/etc/resolv.conf`, + # which nixos-container copies from the host at every start, so the + # hive always uses the host's resolvers. resolvconf is disabled in + # the container (see ./default.nix) so nothing regenerates that + # copy. }; } diff --git a/nix/host-modules/hive-network.nix b/nix/host-modules/hive-network.nix index 5cbc6c9c..c7f6728e 100644 --- a/nix/host-modules/hive-network.nix +++ b/nix/host-modules/hive-network.nix @@ -44,6 +44,12 @@ in hyperhive is enabled; the shared-netns path was removed. Remove the setting. '') + (lib.mkRemovedOptionModule [ "services" "hyperhive" "network" "upstreamDns" ] '' + The hive resolver always follows the host's resolvers now + (dnsmasq reads the gateway container's /etc/resolv.conf, the + host copy made at container start). Configure upstream DNS on + the host itself instead. + '') ]; options.services.hyperhive.network = { @@ -85,26 +91,6 @@ in ''; }; - upstreamDns = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ - "1.1.1.1" - "9.9.9.9" - ]; - example = [ - "192.168.1.1" - "8.8.8.8" - ]; - description = '' - Upstream DNS servers dnsmasq forwards non-hive queries to. - Defaults to Cloudflare + Quad9. Override for operators on - private networks who need a specific resolver (corporate - DNS, pi-hole, etc.). The hive resolver itself stays - authoritative for `` and its sub-domains - regardless of upstream choice. - ''; - }; - exposeHostPorts = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ];