feat: hive DNS always follows the host resolver

This commit is contained in:
müde 2026-07-13 22:08:55 +02:00
commit 935e967718
4 changed files with 28 additions and 28 deletions

View file

@ -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
`<hive-domain>`, `forge.<hive-domain>`, `matrix.<hive-domain>`
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

View file

@ -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

View file

@ -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.
};
}

View file

@ -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 `<hive-domain>` and its sub-domains
regardless of upstream choice.
'';
};
exposeHostPorts = lib.mkOption {
type = lib.types.listOf lib.types.port;
default = [ ];