Do not assume a dhcpcd unit, and refuse to write a placeholder
tests / runner-env (confined) (pull_request) Failing after 1m6s
tests / tests (pull_request) Successful in 1m50s
tests / compose-schema (pull_request) Successful in 1m34s
tests / runner-env (privileged) (pull_request) Successful in 1m22s

Two faults in the resolv.conf step added in the last commit, both hit on a real
host.

It said to run `systemctl disable --now dhcpcd`. There is no such unit on a
current Debian netinst: dhcpcd is invoked by ifup for interfaces set to
`inet dhcp`, not run as a service, so the command fails with "Unit
dhcpcd.service does not exist" in the middle of a sequence whose other lines
did work. The step now checks whether any dhcpcd unit exists and says what
each answer means - nothing listed is the common case and the good one,
because a static interface never calls it and the file just written is the
file that stays.

And it used a `<placeholder>` inside a block written to be pasted. It was
pasted verbatim, which put the literal string into /etc/resolv.conf on two
hosts - a file that looks plausible, is syntactically a nameserver line, and
resolves nothing. That is precisely the class of failure this section exists
to describe, so it should not be reachable by following it.

The address is now assigned to a variable on its own line, and the write is
guarded: anything that is not digits and dots refuses and says to edit the
line above. Getting it wrong now costs a message rather than a host that
cannot resolve and gives no clue why.

61 ok, 0 failed. Documentation only; the guard's two branches were exercised
against a placeholder and an address.
This commit is contained in:
Brad Anderson
2026-08-08 13:32:48 -07:00
parent 8e397737e3
commit 5bec86e29a
+36 -12
View File
@@ -186,23 +186,47 @@ head -1 /etc/resolv.conf
```
**If it says `# Generated by dhcpcd`** — which a current Debian netinst does,
having replaced the older ISC client — then `dhcpcd` owns the file. With the
interface now static it has no lease to work from, so it rewrites it with
comments and no `nameserver` line at all, and the host resolves nothing. Take
it out of the picture, and leave it a fallback in case it ever runs again:
having replaced the older ISC client — then `dhcpcd` wrote it. With the
interface now static it has no lease to take servers from, so what it leaves
behind is three comments and no `nameserver` line at all, and the host resolves
nothing.
Substitute your own address into the first line and paste the rest. The guard
is there because a placeholder pasted verbatim writes a file that looks
plausible and resolves nothing, which is the failure this whole section is
about:
```sh
printf 'nameserver <the nameserver from step 1>\n' | sudo tee /etc/resolv.conf.head
sudo systemctl disable --now dhcpcd
printf 'nameserver <the nameserver from step 1>\n' | sudo tee /etc/resolv.conf
NS=<the nameserver from step 1>
case "$NS" in
*[!0-9.]*|'') echo "REFUSING: '$NS' is not an IP - edit the NS= line first" ;;
*)
printf 'nameserver %s\n' "$NS" | sudo tee /etc/resolv.conf.head >/dev/null
printf 'nameserver %s\n' "$NS" | sudo tee /etc/resolv.conf >/dev/null
getent hosts deb.debian.org && echo "resolves"
;;
esac
```
A statically addressed host has nothing for a DHCP client to do, so disabling
it costs nothing. `resolv.conf.head` is prepended to whatever it would generate
if it came back.
`resolv.conf.head` is prepended to anything `dhcpcd` generates later, so the
entry survives it running again.
**If it says anything else**, or the file carries no header, nothing is
managing it and the last of those three lines is enough on its own.
**Then find out whether it can run again**, because that decides if you are
finished:
```sh
systemctl list-units --all '*dhcpcd*' --no-legend
```
Nothing listed is the common case and the good one: `dhcpcd` is invoked by
`ifup` for interfaces set to `inet dhcp`, and a static interface never calls
it, so the file you just wrote is the file that stays. If a unit *is* listed,
`sudo systemctl disable --now <it>` — a statically addressed host has no use
for a DHCP client, so stopping it costs nothing.
**If the header says anything else**, or the file carries none, nothing is
managing it and writing `/etc/resolv.conf` alone is enough.
`dns-nameservers` inside the interfaces stanza is the other documented way and
it is silently ignored unless `resolvconf` is installed, which it is not here.