DNS resolution on a Linux server is a multi-layered system. When an application calls getaddrinfo("example.com"), the request passes through the Name Service Switch (NSS) framework, which consults sources in the order defined in /etc/nsswitch.conf — typically /etc/hosts first, then a DNS resolver. The DNS resolver reads its configuration from /etc/resolv.conf, which lists the DNS servers and search domains. On RHEL 9, NetworkManager manages /etc/resolv.conf dynamically and can overwrite manual changes on interface up/down events. Understanding all three layers — NSS, /etc/hosts, and /etc/resolv.conf — and how NetworkManager interacts with them is essential for correctly configuring DNS on any RHEL 9 server.
This guide covers configuring /etc/hosts for local resolution, managing /etc/resolv.conf both manually and through NetworkManager, setting per-interface DNS servers and search domains, testing and troubleshooting DNS resolution, and configuring a local caching resolver with systemd-resolved.
Prerequisites
- RHEL 9 server with root or sudo access
- NetworkManager running (default on RHEL 9)
Step 1 — Understand the Resolution Order with nsswitch.conf
The file /etc/nsswitch.conf defines the order in which name resolution sources are consulted:
cat /etc/nsswitch.conf | grep hosts
hosts: files dns myhostname
This means:
- files — check
/etc/hostsfirst - dns — query DNS servers from
/etc/resolv.conf - myhostname — resolve the server’s own hostname via systemd
Change the order only if you have a specific reason (e.g., in containerised environments where DNS must take precedence over hosts file).
Step 2 — Configure /etc/hosts
The /etc/hosts file provides static name-to-IP mappings that bypass DNS entirely. It is read first for every DNS lookup (per the files entry in nsswitch.conf):
vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# Server's own FQDN (must use actual IP, not 127.0.0.1)
203.0.113.10 web01.example.com web01
# Internal cluster members (avoids DNS dependency for critical services)
10.0.0.5 db01.internal.example.com db01
10.0.0.6 db02.internal.example.com db02
10.0.0.10 cache01.internal.example.com cache01
Rules for /etc/hosts:
- The FQDN must come before the short name on the same line
- Use the server’s actual IP address for its own entry (not loopback)
- Changes take effect immediately — no restart needed
- Entries here override DNS for the same name
Step 3 — Understand /etc/resolv.conf and NetworkManager
On RHEL 9, NetworkManager manages /etc/resolv.conf. When a network interface comes up, NetworkManager rewrites the file with DNS settings from the interface configuration. Manual edits to /etc/resolv.conf will be overwritten on the next network event.
# Check if resolv.conf is managed by NetworkManager
ls -la /etc/resolv.conf # May be a symlink
# View current content
cat /etc/resolv.conf
A typical /etc/resolv.conf:
# Generated by NetworkManager
search example.com internal.example.com
nameserver 8.8.8.8
nameserver 8.8.4.4
Step 4 — Configure DNS via NetworkManager (Persistent)
To set DNS servers that survive reboots and interface resets, configure them through NetworkManager:
# List connections
nmcli connection show
# Show DNS settings for a specific connection
nmcli connection show "System eth0" | grep -i dns
# Set DNS servers for a connection
nmcli connection modify "System eth0" ipv4.dns "1.1.1.1 8.8.8.8"
# Set DNS search domains
nmcli connection modify "System eth0" ipv4.dns-search "example.com internal.example.com"
# Disable automatic DNS from DHCP and use only the manually specified ones
nmcli connection modify "System eth0" ipv4.ignore-auto-dns yes
# Apply changes
nmcli connection up "System eth0"
# Verify
cat /etc/resolv.conf
Step 5 — Add DNS Settings to Multiple Interfaces
Servers with multiple NICs (e.g., public-facing eth0 and private backend eth1) need separate DNS configurations:
# Public interface — use public resolvers
nmcli connection modify "System eth0" ipv4.dns "1.1.1.1 8.8.8.8"
nmcli connection modify "System eth0" ipv4.dns-search "example.com"
# Backend interface — use internal resolver for private domains
nmcli connection modify "System eth1" ipv4.dns "10.0.0.1"
nmcli connection modify "System eth1" ipv4.dns-search "internal.example.com"
# Set DNS priority (lower number = higher priority)
nmcli connection modify "System eth0" ipv4.dns-priority 10
nmcli connection modify "System eth1" ipv4.dns-priority 50
nmcli connection up "System eth0"
nmcli connection up "System eth1"
Step 6 — Configure /etc/resolv.conf Options
The options directive in /etc/resolv.conf tunes resolver behaviour. Set these via NetworkManager using the ipv4.dns-options property, or write a static resolv.conf (see Step 7):
options ndots:5 timeout:2 attempts:3 rotate
ndots:5— names with fewer than 5 dots are tried with search domains appended firsttimeout:2— timeout per DNS server query attempt (seconds)attempts:3— retry count per serverrotate— rotate between nameservers instead of always trying the first one first (improves load distribution)
Step 7 — Make resolv.conf Static (Bypass NetworkManager)
In some environments (containers, static server builds), you want a static /etc/resolv.conf that NetworkManager never touches:
# Tell NetworkManager not to manage resolv.conf
vi /etc/NetworkManager/conf.d/no-resolv.conf
[main]
dns=none
systemctl reload NetworkManager
# Now write a static resolv.conf
vi /etc/resolv.conf
search example.com
nameserver 1.1.1.1
nameserver 8.8.8.8
options timeout:2 attempts:3 rotate
# Protect it from accidental overwrites
chattr +i /etc/resolv.conf # Makes the file immutable
lsattr /etc/resolv.conf # Verify
Step 8 — Enable systemd-resolved for Local DNS Caching
systemd-resolved provides a local caching DNS stub resolver (127.0.0.53), which dramatically speeds up repeated DNS lookups and handles per-interface DNS routing:
systemctl enable --now systemd-resolved
# Point resolv.conf at the stub resolver
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
# Configure DNS in /etc/systemd/resolved.conf
vi /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1 8.8.8.8
FallbackDNS=9.9.9.9
Domains=example.com
DNSSEC=yes
DNSOverTLS=opportunistic
Cache=yes
systemctl restart systemd-resolved
# Check resolution status
resolvectl status
Step 9 — Test and Troubleshoot DNS Resolution
# Basic forward lookup
host example.com
nslookup example.com
dig example.com
# Query a specific DNS server directly (bypass resolv.conf)
dig @8.8.8.8 example.com
# Reverse lookup (PTR record)
dig -x 93.184.216.34
# Check which DNS server is being used
dig example.com | grep SERVER
# Test the search domain (short name resolution)
host db01 # Should resolve to 10.0.0.5 if search=internal.example.com
# Flush systemd-resolved cache
resolvectl flush-caches
# Show DNS cache statistics
resolvectl statistics
# Trace the full resolution path
dig +trace example.com
Verification Checklist
# Current resolv.conf
cat /etc/resolv.conf
# NSS order
grep hosts /etc/nsswitch.conf
# NetworkManager DNS config
nmcli connection show "System eth0" | grep -i dns
# Test resolution
getent hosts example.com
getent hosts db01
Troubleshooting
- DNS stops working after reboot — NetworkManager is overwriting your manual
/etc/resolv.conf. Configure DNS throughnmcli(Step 4) or usedns=nonein NetworkManager config (Step 7). - Short names not resolving — check the
searchdirective in/etc/resolv.confand thendotsoption. The search domain must be set. - Slow DNS lookups —
systemd-resolvedwith caching (Step 8) eliminates repeated lookups. Also check for failed first-server queries causing timeouts: reducetimeoutin resolv.conf options.
Conclusion
Your RHEL 9 server now has a correctly layered DNS configuration: static entries in /etc/hosts for critical internal hosts, persistent DNS server configuration through NetworkManager, and optionally a local caching resolver via systemd-resolved. You understand the resolution order and can diagnose failures at each layer.
Next steps: How to Use rsync for Efficient File Synchronisation on RHEL 9, How to Configure the Firewall on RHEL 9, and How to Set a Hostname and FQDN on RHEL 9.