Point builds at miren's bridge DNS instead of public DNS - #1103
Conversation
Build RUN steps run in the host network namespace, but buildkit generates their resolv.conf as if they were sandboxed: it strips the host's loopback stub resolver (systemd-resolved's 127.0.0.53) and substitutes public DNS (8.8.8.8). On a host with an internal-only or egress-filtered resolver, builds then can't resolve names at all. Add a [dns] section to the generated buildkitd.toml pointing at miren's own bridge DNS server, wired in from the network boot node's router address. That resolver already serves runtime sandboxes: it forwards to the host's real upstream and answers *.app.miren. The bridge gateway is a local interface in the host netns, so build steps can reach it, and buildkit keeps it since it isn't a loopback address. Fixes MIR-1695
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: 5 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 6 reviews per hour. 📝 WalkthroughWalkthroughBuildKit configuration now accepts optional DNS nameservers. When configured, generated TOML includes a quoted Merge Risk: ⚪ Minimal · up to Builds will use Miren’s bridge DNS instead of public resolvers, restoring name resolution for hosts with internal DNS configurations. No actionable merge-blocking risk remains beyond normal checks and review. Comment |
There was a problem hiding this comment.
🍪 biscuit: ✅ ready to merge — auto-review, non-blocking
I read through all four changed files and traced the full path from networkBootOutput.routerAddress through to the generated buildkitd.toml. This is a tight, focused fix with a clear problem statement.
The problem is real and the fix is correct. BuildKit strips loopback nameservers (the whole 127.0.0.0/8 range) and falls back to 8.8.8.8 when constructing resolv.conf for build steps. On hosts using systemd-resolved's 127.0.0.53 stub this silently breaks builds behind internal or egress-filtered resolvers. Pointing the [dns] section at miren's bridge router address — a non-loopback address reachable from the host netns — routes around this correctly.
Implementation details I checked:
network.routerAddress.IsValid()guards the zero-value case before constructing the nameserver list. If the network boot hasn't set a router address for any reason,dnsNameserversstaysnilandgenerateConfigemits no[dns]section, leaving buildkit's default behavior intact. Safe fallback.- Nameserver quoting uses
fmt.Sprintf("%q", ns), which fornetip.Addr.String()output (a well-formed IP address) produces valid TOML string literals. No injection risk since the value comes from a typednetip.Addr, not user input. - The
%[4]sslot replaces the blank line between[log]and[grpc]in the template. WhendnsSectionis non-empty it starts with\nand ends with\n, so the section boundary stays clean. When it's empty the blank line disappears — cosmetically different but perfectly valid TOML. - The boot graph wiring is clean:
network.outputflows intonewBuildkitBoot→startEmbedded, parallel to howregistryHostMappingwas already wired.
Tests: The two new test cases cover what matters — single and multiple nameservers produce the right TOML, and no [dns] section appears when the slice is nil. The existing "no hardcoded DNS" test was correctly reframed to check absence of [dns] rather than nameservers=.
One small cosmetic note: the generateConfig signature now takes four arguments where the first three were positional and the fourth is the DNS slice. The %[1]d/%[2]d/%[3]s/%[4]s explicit indexing in the format string makes the argument mapping clear and immune to accidental reordering. Good call.
Nothing blocking here — this is ready to merge.
🍪 full review note · comment /biscuit review to run biscuit again.
Problem
Container image builds silently resolve DNS against public servers (
8.8.8.8/8.8.4.4) instead of the host's configured resolver. On a host that uses a systemd-resolved stub —nameserver 127.0.0.53in/etc/resolv.conf— with an internal-only or egress-filtered upstream, builds can't resolve names at all. Reported by a user whose build environment couldn't do DNS.Root cause
Build
RUNsteps run in the host network namespace (with no CNI config, buildkit's "auto" mode falls back to host networking), but buildkit generates each build's resolv.conf as if it were sandboxed. The step'sNetModeisUNSET, notHOST, soGetResolvConfstrips every loopback nameserver (the whole127.0.0.0/8range,127.0.0.53included) and, finding none left, substitutes8.8.8.8/8.8.4.4. It can't recover the real upstream either, since/run/systemd/resolve/resolv.confisn't mounted into buildkitd — only the host's/etc/resolv.confis, viaoci.WithHostResolvconf.So even though the build sits in the very netns where
127.0.0.53would resolve, buildkit discards it and hardcodes public DNS — the "breaks builds on hosts with an internal resolver" case the earlier MIR-1643 note meant to avoid.Fix
Add a
[dns]section to the generatedbuildkitd.tomlpointing at miren's own bridge DNS server, wired in from the network boot node's router address. That resolver already serves runtime sandboxes: it forwards to the host's real upstream and answers*.app.miren. The bridge gateway is a local interface in the host netns, so build steps reach it, and buildkit keeps it (not a loopback, so the filter leaves it alone). External buildkit daemons are untouched.Verification
TestGenerateConfig) and server boot/startup tests pass;golangci-lint run ./...reports 0 issues.RUN cat /etc/resolv.conf→nameserver 8.8.8.8nameserver 10.8.13.1, andnslookup example.comresolves through it (exit=0)Fixes MIR-1695