From fa5e5cb91267bff0d3205f6a947fa4346366bc4a Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 14 Sep 2026 18:45:40 +0200 Subject: [PATCH] Configure the resolver rather than fight it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first attempt wrote /etc/resolv.conf. On these images that is a symlink owned by systemd-resolved, so the file is either reverted or the link is broken — found by reading a running machine instead of assuming the change had worked. The real shape shows in resolvectl: the machine has sensible global fallbacks, and the link carrying the default route has exactly one server, the uplink gateway. resolved will not reach a global fallback while the link has a server of its own, so one unanswered packet is one failed lookup. Three runs have died that way, each long after the egress check passed. The uplink stays first, so the modelled path is still what is used and still what the check proves. Verified on a live machine: three servers on the link, uplink first, resolution intact. --- src/lifecycle/egress.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/lifecycle/egress.ts b/src/lifecycle/egress.ts index 386018b..e2b4995 100644 --- a/src/lifecycle/egress.ts +++ b/src/lifecycle/egress.ts @@ -131,19 +131,28 @@ async function reaches(name: string, waitSeconds: number): Promise { await incus([ "exec", name, "--", "sh", "-c", - `via=$(ip -4 route show default | awk '{print $3}' | head -n1); ` + - `{ [ -n "$via" ] && printf 'nameserver %s\\n' "$via"; ` + - `printf 'nameserver 1.1.1.1\\nnameserver 8.8.8.8\\n'; ` + - `printf 'options timeout:2 attempts:3\\n'; } > /etc/resolv.conf; true`, + `link=$(ip -4 route show default | awk '{print $5}' | head -n1); ` + + `via=$(ip -4 route show default | awk '{print $3}' | head -n1); ` + + `if [ -n "$link" ] && command -v resolvectl >/dev/null 2>&1; then ` + + `resolvectl dns "$link" $via 1.1.1.1 8.8.8.8 >/dev/null 2>&1 || true; fi; true`, ], 30_000); }