resolvconf will silently fail to update (replace) the contents of
/etc/resolv.conf when running as a dhcpcd hook. It will leave
/etc/resolv.conf with the empty template that was generated prior to
dhcpcd starting, with no 'nameserver' entry, therefore having glibc
default to 127.0.0.1 as its nameserver.
When resolvconf is installed, the 20-resolv.conf dhcpcd hook will invoke
it instead of writing /etc/resolv.conf on its own
(have_resolvconf=true).
resolvconf sets up /etc/resolv.conf as a symlink to
/run/resolvconf/resolv.conf. After generating its temporary copy of
resolv.conf, it does a rename to replace /run/resolvconf/resolv.conf.
The systemd unit file for dhcpcd sets up a sandbox and adds
/etc/resolv.conf to the list of ReadWritePaths=, which makes sense since
in the default configuration, /etc/resolv.conf is not a symlink.
However, with resolvconf installed, ReadWritePaths="... /etc/resolv.conf"
resolves to a bind-mount of /run/resolvconf/resolv.conf in dhcpcd's
namespace, and any attempt by resolvconf (running as a hook in that
namespace) to mv over it results in EBUSY, causing resolvconf to fail:
+ mv -f /run/resolvconf/resolv.conf_new.1844 /run/resolvconf/resolv.conf
mv: cannot move '/run/resolvconf/resolv.conf_new.1844' to '/run/resolvconf/resolv.conf': Device or resource busy
For my own setup, I did an override of the systemd unit file and removed
/etc/resolv.conf from ReadWritePaths since /run is already writable (not
sure how given that ProtectSystem=strict is set; /etc and /usr are
correctly read-only), so resolvconf can properly regenerate the target.
But that would not work in the default case since /etc/resolv.conf would
still be a static file under /etc, which _is_ read-only inside the
sandbox.
I saw #1133083 mentions dhcpcd should do like resolvconf (and
systemd-resolved, and others), and manage a symlink instead of a static
/etc/resolv.conf, which could be one way to fix this.
Or some way to conditionally add /etc/resolv.conf to ReadWritePaths=.