Configure DNS settings

Change DNS servers on Fedora using NetworkManager's nmcli command or by editing the systemd-resolved configuration file.

The scenario

You plug your laptop into a corporate network or a public hotspot. The connection indicator turns green, but your package manager hangs on metadata downloads. Your browser loads some sites but fails on others. The network interface is up, but name resolution is broken. You need to point Fedora at a specific DNS server, but editing /etc/resolv.conf stopped working years ago. The system ignores your changes, or a reboot wipes them out. You need a reliable way to configure DNS that survives connection changes and aligns with how Fedora actually routes queries.

How Fedora handles DNS

Fedora uses NetworkManager to manage network interfaces and systemd-resolved to handle DNS queries. These two services work in a pipeline. NetworkManager talks to DHCP servers, pulls down IP addresses, routes, and DNS server addresses, then passes that information to systemd-resolved. The resolver caches queries, validates DNSSEC signatures, and maintains a local stub resolver at /run/systemd/resolve/stub-resolv.conf. That stub file listens on 127.0.0.53 and forwards queries to the upstream servers NetworkManager provided.

The file /etc/resolv.conf is a symbolic link pointing to that stub resolver. If you break the symlink and create a static file, systemd-resolved stops updating it. The next DHCP lease renewal or reboot leaves you with stale IP addresses or complete resolution failures. You must configure DNS through the tools that control the pipeline. NetworkManager handles per-connection routing. systemd-resolved handles global fallbacks and caching. They share state through D-Bus, not through static text files.

Understanding this pipeline prevents the most common configuration mistakes. You are not editing a configuration file. You are telling NetworkManager which servers to advertise to the resolver, or telling the resolver which servers to use when no connection provides one. The architecture is designed to keep your DNS settings isolated per network while maintaining a single caching layer.

Run journalctl -xeu systemd-resolved when things go wrong. The x flag adds explanatory context and the e flag jumps to the end. Most resolver failures leave a clear trace in the journal before they cascade into application errors.

Set DNS per connection

This is the standard approach for desktop and laptop users. You tell NetworkManager which DNS servers to use for a specific connection profile. When you connect to that network, the settings apply. When you disconnect, they stay dormant. This keeps your home network, work network, and mobile hotspot configurations isolated. It also ensures that DHCP-provided settings do not interfere with your manual choices.

List your active and saved connections first.

nmcli connection show
# WHY: Shows all saved connection profiles and their current state.
# Look for the NAME column to identify the exact profile you want to modify.
# The UUID column helps if you have duplicate names across different interfaces.

Apply your preferred DNS servers to that profile. Replace Wired connection 1 with your actual connection name.

sudo nmcli connection modify "Wired connection 1" ipv4.dns "1.1.1.1 8.8.8.8"
# WHY: Sets the primary and secondary DNS servers for IPv4 on this profile.
# NetworkManager will pass these addresses to systemd-resolved on activation.
sudo nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
# WHY: Stops DHCP from overwriting your manual servers with the router's defaults.
# Without this flag, the next lease renewal will wipe your custom configuration.
sudo nmcli connection up "Wired connection 1"
# WHY: Reactivates the connection to apply the new DNS configuration immediately.
# This forces NetworkManager to push the updated settings to the resolver.

If you also need IPv6 DNS, repeat the process with ipv6.dns and ipv6.ignore-auto-dns. NetworkManager merges IPv4 and IPv6 resolver settings automatically. The resolver prefers IPv6 when the interface has a global IPv6 address and the DNS servers support it.

Save the connection profile, not the interface. Profiles travel with you across networks and survive hardware changes.

Set system-wide fallback DNS

Sometimes you need a baseline resolver that applies everywhere, even when NetworkManager hands you a broken DHCP response or when you are on an unmanaged interface. systemd-resolved supports a global fallback list. These servers only activate when the per-connection DNS fails to respond or returns a SERVFAIL error.

Edit the resolver configuration file. Always modify files in /etc/. Never touch /usr/lib/ or /run/. Package managers overwrite /usr/lib/ on updates, and /run/ clears on reboot.

[Resolve]
DNS=1.1.1.1 8.8.8.8
# WHY: Sets the default DNS servers for all interfaces that do not provide their own.
# These servers become active when NetworkManager reports no DNS for a connection.
FallbackDNS=9.9.9.9 1.0.0.1
# WHY: Activates only when the primary DNS servers time out or return SERVFAIL.
# This creates a resilient chain without polluting successful queries.
Domains=~.
# WHY: The tilde marks these servers as routable, preventing them from leaking to non-local queries.
# This ensures fallback servers only handle global internet lookups.

Restart the resolver service to load the new configuration.

sudo systemctl restart systemd-resolved
# WHY: Forces systemd-resolved to re-read /etc/systemd/resolved.conf and apply the fallback list.
# The service reloads its configuration without dropping active connections.

Fallback servers are a safety net, not a replacement for correct per-network configuration.

Verify and test resolution

Check what the system is actually using. resolvectl is the official tool for inspecting systemd-resolved. It reads directly from the resolver's internal state instead of parsing static files.

resolvectl status
# WHY: Displays the active DNS servers per interface, DNSSEC validation state, and cache metrics.
# The output is organized by interface, making it easy to spot misrouted queries.

Look for the DNS Servers line under your active interface. If you see 127.0.0.53, that is the local stub resolver. It is working correctly. The actual upstream servers appear in the DNS Servers section above it. If you see 127.0.0.53 as the only entry, the resolver is routing queries locally but has no upstream servers configured for that interface.

Test a live query to confirm resolution is routing correctly.

resolvectl query fedoraproject.org
# WHY: Sends a query through the active resolver and prints the resolved IP addresses.
# This bypasses application-level caching and shows exactly what the system resolves.

If you need to verify DNSSEC validation, check the output for SECURE or INSECURE. SECURE means the chain of trust validated successfully. INSECURE means the domain does not support DNSSEC, which is normal for many public sites. BOGUS means validation failed. You will see BOGUS if a resolver returns a forged signature or if your fallback server does not support DNSSEC validation.

Run resolvectl status before you guess. The output tells you exactly which server answered the query and whether caching is active.

Common pitfalls and error patterns

The most common mistake is editing /etc/resolv.conf directly. Fedora ships this file as a symbolic link to /run/systemd/resolve/stub-resolv.conf. If you break the symlink and create a static file, systemd-resolved stops updating it. You will see stale IP addresses or complete resolution failures after a reboot. The terminal will not print an error. Applications will simply hang or return Could not resolve host.

Another frequent issue is DHCP overriding manual settings. If you set ipv4.dns but forget ipv4.ignore-auto-dns yes, the next DHCP lease renewal will wipe your custom servers. The terminal will show no error, but your queries will suddenly route to the ISP's resolver. Check nmcli connection show <name> to verify the ipv4.ignore-auto-dns property is set to yes.

Split-DNS configurations require search domains. If your internal services use .local or a private zone, you must tell NetworkManager which domains to route to which servers.

sudo nmcli connection modify "Work Network" ipv4.dns-search "corp.internal"
# WHY: Tells the resolver to append .corp.internal to unqualified hostnames on this connection.
# This allows you to type `ping mail` instead of `ping mail.corp.internal`.

If you encounter persistent resolution failures, flush the cache and check the journal.

sudo resolvectl flush-caches
# WHY: Clears the in-memory DNS cache to force fresh queries to upstream servers.
# Useful when upstream servers change IPs but the local cache still holds old records.
journalctl -xeu systemd-resolved | tail -20
# WHY: Shows recent resolver logs with explanatory context.
# Look for `Failed to resolve` or `DNSSEC validation failed` messages.

Trust the symlink. Manual file edits drift, resolver pipelines stay consistent.

Choose the right approach

Use per-connection DNS when you move between networks and need isolated resolver settings. Use system-wide fallback DNS when you want a guaranteed resolver during DHCP failures or unmanaged interfaces. Use split-DNS search domains when you connect to corporate networks with internal service zones. Stay on the default DHCP-provided DNS when you are on a trusted home network and do not need custom routing.

Where to go next