DNS Resolver Configuration on Linux: Changes That Actually Take Effect
How to properly configure and apply DNS resolver changes on Linux, including systemd-resolved, resolv.conf management, and debugging DNS issues.
Introduction
DNS is the phone book of the internet, and on Linux, getting it configured correctly is surprisingly complicated. Different distributions manage DNS differently, and making changes that persist across reboots requires understanding which tool owns your resolver configuration. This post covers the common DNS configuration methods on Linux, why changes sometimes do not take effect, and how to debug DNS resolution issues.
Environment
The examples use Ubuntu 22.04 with systemd-resolved as the default DNS resolver, and a secondary Debian 12 server using traditional /etc/resolv.conf. Both are common in production environments.
resolvectl --version
# systemd 249 (249.11-0ubuntu3.12)Problem
You update /etc/resolv.conf to use a new DNS server:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.confBut after a few minutes or a network restart, the changes revert:
cat /etc/resolv.conf
# nameserver 127.0.0.53 # Back to the old one!Or DNS resolution works partially but certain domains fail:
nslookup internal.company.com
# ** server can't find internal.company.com: NXDOMAIN
nslookup google.com
# Server: 8.8.8.8
# Address: 8.8.8.8#53
# Non-authoritative answer:Analysis
On modern Linux systems, DNS resolution is managed by one of several layers:
- systemd-resolved (Ubuntu 18.04+, Fedora, modern distros)
- NetworkManager (desktop and some server setups)
- Resolvconf (traditional Debian/Ubuntu)
- Direct /etc/resolv.conf (minimal or static configurations)
The /etc/resolv.conf file is often a symlink managed by one of these tools:
ls -la /etc/resolv.conf
# lrwxrwxrwx 1 root root 39 Mar 25 10:00 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.confWriting directly to a symlinked resolv.conf will be overwritten by the managing service.
Solution
1. For systemd-resolved systems
Check the current configuration:
resolvectl status
# Global
# Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
# resolv.conf mode: stub
#
# Link 2 (eth0)
# Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
# Protocols: +DEFAULT +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
# DNS Servers: 192.168.1.1 8.8.8.8Change DNS servers:
# For a specific link
sudo resolvectl dns eth0 8.8.8.8 1.1.1.1
# Persistently via network config
sudo nano /etc/systemd/resolved.conf[Resolve]
DNS=8.8.8.8 1.1.1.1
FallbackDNS=9.9.9.9
#Domains=~.
#DNSSEC=allow-downgrade
#DNSOverTLS=opportunisticRestart systemd-resolved:
sudo systemctl restart systemd-resolved2. For NetworkManager systems
# Set DNS for a connection
sudo nmcli con mod "Wired connection 1" ipv4.dns "8.8.8.8 1.1.1.1"
sudo nmcli con mod "Wired connection 1" ipv4.ignore-auto-dns yes
sudo nmcli con up "Wired connection 1"3. For static /etc/resolv.conf (unmanaged systems)
If no service manages your resolv.conf:
sudo chattr +i /etc/resolv.conf # Make immutable to prevent overwritesOr remove the systemd-resolved package entirely:
sudo apt-get remove --purge systemd-resolved
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf4. Debug DNS resolution
# Test with dig
dig @8.8.8.8 internal.company.com
# Test with systemd-resolved
resolvectl query internal.company.com
# Check which DNS server is being used for a domain
resolvectl query internal.company.com | grep "DNS Server"5. Use split DNS for internal/external domains
# /etc/systemd/resolved.conf
[Resolve]
DNS=8.8.8.8
# /etc/systemd/resolved.conf.d/internal.conf
[Resolve]
DNS=192.168.1.10
Domains=~company.internal6. Flush DNS cache
resolvectl flush-caches7. Check for DNS resolution issues with systemd-resolved
resolvectl statistics
# Current Cache Size: 1234
# Cache Hits: 5678
# Cache Misses: 890Lessons Learned
DNS configuration on Linux is managed by layers, and fighting against those layers leads to frustration. Always identify which tool manages your resolv.conf before making changes. Use resolvectl on systemd-resolved systems instead of editing files directly. And for split DNS setups (internal vs external domains), systemd-resolved's domain routing is the cleanest approach. Test with dig and resolvectl query to verify your changes are working.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.