Disable systemd-resolved Cleanly
Over the last several years, systemd has steadily absorbed an increasing number of Linux functions that were previously simple config files and/or binaries. I honestly don’t have a strong opinion on systemd
but it does make certain system admin-y tasks more complicated. One of the things that I reguarly run into is that systemd-resolved
runs a “stub” DNS server that binds on 127.0.0.53:53
and takes over /etc/resolv.conf
. Rather than being a text file, /etc/resolv.conf
is instead, by default, a symlink to /run/systemd/resolve/stub-resolv.conf
which uses the aforementioned stub DNS server as its nameserver.
For most use-cases, this works great and the stub DNS server provides some useful additional functionality. Unfortuantely, it also causes problems if you want to install a real DNS server as at least one interface already has a service bound on UDP port 53. This caused me problems when I spun up a pi-hole virtual machine (VM) as well as when I wanted to install a full-featured DNS server for my WireGuard VM. Searching around can lead you to several forums with people giving different advice.
The Common Solution
Outright disabling systemd-resolved
has the nasty side effect of losing the ability to use DHCP to set your DNS server as that task is now delegated to systemd-resolved
. Instead, many people point to editing /etc/systemd/resolved.conf
, setting DNSStubListener
to “no”, and then restarting systemd-resolved
. Here’s what /etc/systemd/resolved.conf
looks like afterwards:
[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#DNSOverTLS=no
#Cache=no-negative
DNSStubListener=no
#ReadEtcHosts=yes
You then need to set /etc/resolv.conf
to be a symlink to /run/systemd/resolve/resolv.conf
. This version of the resolv.conf
is a managed file that bypasses the stub DNS server but still respects the DNS server set by DNS (or netplan). You can create the symlink and restart systemd-resolved
by doing:
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl restart systemd-resolved
I did this up until recently and then discovered that, since /etc/systemd/resolved.conf
is installed by by a .deb
, modifying it causes unattended-upgrade to fail out when systemd
has an update because it wants a manual review of the clobbered config file.
The Clean Solution
I happened to be reading the man page for resolved.conf when I noticed that systemd-resolved
supports “drop-in” config files. In general, drop-in config files have the benefit of still configuring the target program but not be controlled by a .deb file. This means that unattended-upgrade
can still do its thing and not run into a situation where it wants a human to compare clobbered files. You first need to make the drop-in config file directory using:
sudo mkdir -p /etc/systemd/resolved.conf.d/
You then need to make a file at /etc/systemd/resolved.conf.d/disable-stub.conf
(the name doesn’t matter but it must end in a “.conf”) with the following contents:
[Resolve]
DNSStubListener=no
As before, you still need to repoint /etc/resolv.conf
to the non-stub file and restart systemd-resolved:
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl restart systemd-resolved
The stub DNS server should now be disabled and you’ll be prompted to do fewer manual reviews of config files in the future!