devops2025-03-25·11 min·138/348

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.conf

But 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:

  1. systemd-resolved (Ubuntu 18.04+, Fedora, modern distros)
  2. NetworkManager (desktop and some server setups)
  3. Resolvconf (traditional Debian/Ubuntu)
  4. 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.conf

Writing 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.8

Change 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=opportunistic

Restart systemd-resolved:

sudo systemctl restart systemd-resolved

2. 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 overwrites

Or remove the systemd-resolved package entirely:

sudo apt-get remove --purge systemd-resolved
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

4. 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.internal

6. Flush DNS cache

resolvectl flush-caches

7. Check for DNS resolution issues with systemd-resolved

resolvectl statistics
# Current Cache Size: 1234
# Cache Hits: 5678
# Cache Misses: 890

Lessons 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.