diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index e510de50..aef3ec2c 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -342,47 +342,32 @@ in # tuwunel hard-fails to boot if `/etc/resolv.conf` has no # `nameserver` line (`Failed to configure DNS resolver ... no # nameservers found in config` → exit 1). This declarative - # nixos-container comes up with an EMPTY resolv.conf even with - # `networking.nameservers` set: the nixos-container default - # `useHostResolvConf = true` puts in-container resolvconf in - # host-tracking mode (ignores `networking.nameservers`, and never - # gets the host file across the shared-netns boundary), so it - # regenerates an empty file and tuwunel dies at boot. + # nixos-container had it come up EMPTY (just `options edns0`) + # even with `networking.nameservers` set: the nixos-container + # default `useHostResolvConf = true` puts in-container resolvconf + # in host-tracking mode, which ignores `networking.nameservers` + # and never receives the host's resolv.conf across the + # shared-netns boundary — so resolvconf regenerates an empty file + # and tuwunel dies at boot. # - # The earlier fix turned host-tracking off and trusted resolvconf - # to honour `networking.nameservers` — but that's a RUNTIME - # resolvconf behaviour, not verifiable at eval time, and it STILL - # came up empty in practice. So take resolvconf out of the - # loop entirely and write a STATIC `/etc/resolv.conf` from - # `bridgeIp` that nothing regenerates. Eval-proven: the generated - # `environment.etc."resolv.conf".text` is `nameserver `. + # When the hive network module is on, turn off host-tracking so + # resolvconf honours `networking.nameservers`, pointing the + # resolver at the dnsmasq the network module runs at `bridgeIp`. # This container always shares the host netns - # (`privateNetwork = false`), so it reaches `bridgeIp` regardless - # of `isolateContainers`. Network module off → inherit the host's - # resolv.conf. See `docs/network.md`. + # (`privateNetwork = false`), so it reaches `bridgeIp` whether or + # not `isolateContainers` is set. With the network module off, + # inherit the host's resolv.conf (which carries the host + # resolver). See `docs/network.md`. networking = lib.mkMerge [ (lib.mkIf networkCfg.enable { - # resolvconf is taken out of the loop entirely; the static - # `environment.etc."resolv.conf"` below is the sole source of - # the resolver file (no `nameservers` — nothing would read it). useHostResolvConf = lib.mkForce false; - resolvconf.enable = lib.mkForce false; + nameservers = [ networkCfg.bridgeIp ]; }) (lib.mkIf (!networkCfg.enable) { useHostResolvConf = true; }) ]; - # resolvconf is disabled above, so write the static resolver file - # explicitly — NixOS won't synthesise one from `nameservers` once - # resolvconf is off, and this is the file tuwunel parses at boot. - environment.etc = lib.mkIf networkCfg.enable { - "resolv.conf".text = '' - nameserver ${networkCfg.bridgeIp} - options edns0 - ''; - }; - services.matrix-tuwunel = { enable = true; package = cfg.package;