resolv.conf and systemd-resolved
Introduction¶
/etc/resolv.conf traditionally listed your nameservers. On current
Ubuntu/Fedora/RHEL it's frequently a symlink to a file managed by
systemd-resolved (or NetworkManager), and hand-edits get overwritten. You
need to know which model your box uses.
The possibilities¶
Check what /etc/resolv.conf actually is:
ls -l /etc/resolv.conf
| Target | Manager | Edit where |
|---|---|---|
../run/systemd/resolve/stub-resolv.conf |
systemd-resolved (stub at 127.0.0.53) | resolvectl / .network files / NM |
../run/systemd/resolve/resolv.conf |
systemd-resolved (writes real upstreams directly) | same |
/run/NetworkManager/resolv.conf |
NetworkManager | nmcli |
| a real file | nobody — you own it | edit directly |
systemd-resolved¶
resolved runs a stub listener on 127.0.0.53:53. stub-resolv.conf contains
just nameserver 127.0.0.53. Applications query the stub; resolved forwards to
the real upstreams it learned from DHCP / config, applies per-link routing,
caches, and does DNSSEC validation if enabled.
Set DNS:
# Per interface, at runtime
resolvectl dns eth0 1.1.1.1 9.9.9.9
resolvectl domain eth0 example.com '~corp.internal' # ~ = routing-only domain
# Persistently via a .network file (systemd-networkd)
# /etc/systemd/network/10-eth0.network
[Match]
Name=eth0
[Network]
DNS=1.1.1.1
Domains=example.com ~corp.internal
# Or global fallback: /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1
FallbackDNS=9.9.9.9
DNSSEC=allow-downgrade
systemctl restart systemd-resolved after editing config files.
Split DNS¶
The killer feature: route different domains to different servers. A
"routing-only" domain (~corp.internal) on the VPN interface means only
*.corp.internal queries go to the corporate DNS; everything else uses your
normal resolver. No more "the VPN broke all my DNS".
resolvectl domain tun0 '~corp.internal' '~10.in-addr.arpa'
resolvectl dns tun0 10.0.0.53
Debugging¶
resolvectl status # per-link DNS servers, domains, DNSSEC state
resolvectl query example.com # resolve via resolved (shows which link/server answered)
resolvectl statistics # cache hits, DNSSEC
resolvectl flush-caches
resolvectl reset-server-features # after changing upstreams that misbehaved
# Bypass resolved entirely to test upstream directly
dig @1.1.1.1 example.com
dig @127.0.0.53 example.com # via the stub
nslookup/dig with no @server may or may not go through the stub depending
on the tool — dig reads /etc/resolv.conf (so the stub), resolvectl query
is the definitive "what does the system do".
Verification and troubleshooting¶
- Edited
/etc/resolv.conf, reverted on reboot/reconnect — it's managed. Useresolvectl/ NM /.network. To take manual control:rm /etc/resolv.conf; echo 'nameserver 1.1.1.1' > /etc/resolv.confand disable the manager (orsystemctl disable --now systemd-resolvedand point the symlink elsewhere). resolvectl statusshows the right DNS but resolution fails — the app isn't using NSS//etc/resolv.conf(Go binaries withCGO_ENABLED=0use their own resolver reading/etc/resolv.confdirectly — fine — but musl/alpine containers differ), ornsswitch.confhosts:line is odd.- VPN breaks all DNS — the VPN pushed a
Domains=~.(route everything) or replaced the global DNS. Scope it: routing-only domains for the internal zones, keep the default resolver for the rest. - Slow first lookup, then fast — cache is working; the slow one is the
upstream.
resolvectl statisticsfor hit rate. - DNSSEC failures on a captive portal / corporate resolver —
DNSSEC=allow-downgradetolerates resolvers that strip DNSSEC;DNSSEC=nodisables it. 127.0.0.53in a container — the stub isn't there; the container has its own/etc/resolv.conf. Don't copy the host's.getent hosts xworks,dig xfails (or vice versa) —getentuses NSS (includes/etc/hosts, mDNS);digis pure DNS. The difference tells you where the name is defined.
Related tools and reading¶
- On-site: DNS lookup, DNS propagation checker.
- Related posts: DNS resolution, step by step, nmcli: common tasks without the GUI.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Linux & Sysadmin
Tuning Open File Limits on Linux
Four different limits control how many files a process can open. 'Too many open files' means you're hitting one specific one — here's how to find and raise it.
October 24, 2026ss and conntrack for Connection Debugging
ss shows you every socket and its send/receive queues; conntrack shows what the firewall is tracking. Together they explain most 'connection refused' and 'no buffer space' problems.
October 24, 2026How systemd Unit Files Work
A practical walk through writing your first systemd service: the three sections, the dependency model, and how to debug one that won't start.
October 24, 2026