Ubuntu 24.04 Noble Numbat ships with systemd-resolved baked deep into its networking stack, and that changes everything about how DNS configuration works. Editing /etc/resolv.conf directly — the muscle-memory move from older Linux — either breaks silently or gets overwritten on reboot. To reliably change DNS servers, you need to work with the tools that actually own the configuration: Netplan, resolved.conf, resolvectl, or NetworkManager. This article walks through every method, explains which one fits your setup, and shows you how to verify the change actually took effect.
How systemd-resolved Controls DNS in Ubuntu 24.04
systemd-resolved is a local stub resolver daemon that listens on 127.0.0.53 port 53. Every DNS query from every application on your machine goes there first. The resolver then forwards upstream to whichever nameservers are configured — either per-interface (set via Netplan or NetworkManager) or from a global fallback in /etc/systemd/resolved.conf.
The critical thing to understand: /etc/resolv.conf is a symlink, not a real file. Run this to confirm:
You will see output similar to:
That target file contains a single line: nameserver 127.0.0.53. It is generated and owned by systemd-resolved. Writing into it directly accomplishes nothing — the resolver regenerates it fresh whenever the service restarts or the network comes up.
There is also a second target, /run/systemd/resolve/resolv.conf (without the stub- prefix), which contains the actual upstream servers in plain text. Some older guides tell you to repoint the symlink there. Avoid this on Ubuntu 24.04 — it bypasses DNSSEC validation, split-DNS, and DNS-over-TLS features that systemd-resolved provides when operating through the stub.
Check Your Current DNS State Before Changing Anything
Run these two commands to snapshot your current nameservers and confirm the stub resolver is alive:
resolvectl status shows per-link and global DNS servers, active search domains, DNSSEC state, and whether DNS-over-TLS is negotiated. Look for the DNS Servers line under each interface. The dig query confirms the stub is responding. If it times out, systemd-resolved has a problem — check with systemctl status systemd-resolved.
Also find which Netplan file controls your interface:
The filename varies. Common names are 00-installer-config.yaml on server installs and 01-network-manager-all.yaml on desktop. Read whatever is present before editing.
Method 1: Netplan — Recommended for Servers and Most Setups
Netplan is the canonical configuration layer on Ubuntu 24.04. Changes here persist across reboots, survive package upgrades, and integrate cleanly with systemd-resolved's per-link DNS architecture. Use this method for VMs, cloud instances, and bare-metal servers.
Open your Netplan config — adjust the filename to match what ls /etc/netplan/ returns:
A typical DHCP server config looks like this:
To pin specific DNS servers, add the nameservers block under the interface. This overrides whatever the DHCP server hands you:
Replace ens3 with your actual interface name (check with ip link show). Common names on Ubuntu 24.04 include ens3, ens18, eth0, and enp3s0 depending on the hypervisor or hardware. Replace the addresses with your desired DNS servers — Cloudflare (1.1.1.1 / 1.0.0.1), Google (8.8.8.8 / 8.8.4.4), or your own internal resolver. Include domain names in the search list only if you need short-name resolution; otherwise leave it empty.
Apply the change without disrupting active connections:
Verify immediately:
If netplan apply reports a parse error, YAML indentation is almost always the cause. Netplan requires consistent two-space indentation — tabs are not allowed.
Method 2: /etc/systemd/resolved.conf — Global Fallback DNS
This method sets a DNS server that applies when no per-link DNS is configured, or when an interface's assigned DNS fails. It is also where you enable DNS-over-TLS and DNSSEC globally. Think of it as the floor-level setting that Netplan overrides on a per-interface basis.
Open the config file:
The file ships with all options commented out. Uncomment and configure the relevant lines:
What each option does:
- DNS: primary upstream servers, space-separated. These apply globally when no per-link DNS is set.
- FallbackDNS: used only when the primary list is unreachable. Keeps the machine online during an upstream outage.
- Domains=~.: the tilde-dot routing hint means use this server for all domains. Without it, the global fallback may not win for queries that don't match a more specific domain route.
- DNSSEC=allow-downgrade: validates DNSSEC for signed zones, falls back gracefully for unsigned ones. Use true for strict enforcement or false to disable entirely.
- DNSOverTLS=opportunistic: attempts TLS encryption on port 853, falls back to plaintext if the server doesn't support it. Use yes for strict DoT mode.
Restart the resolver to apply:
Verify with resolvectl status and look for the Current DNS Server line in the global section at the top of the output.
Method 3: NetworkManager — Desktop Ubuntu
Desktop Ubuntu 24.04 runs NetworkManager alongside Netplan. NetworkManager is what the GNOME Settings app writes to, so any GUI-made changes go through it. Use this method if you are on a desktop and want to avoid editing YAML directly.
Using nmcli
List your connections first to find the correct name:
Set static DNS on a connection — adjust the name to match your output:
The ignore-auto-dns yes flag prevents DHCP from overwriting your setting on the next lease renewal. Without it, the router pushes its own DNS back over yours automatically every time the lease renews.
Using GNOME Settings
- Open Settings → Network
- Click the gear icon next to your active connection
- Go to the IPv4 tab
- Leave Method as Automatic (DHCP) but turn off the Automatic DNS toggle
- Enter DNS servers comma-separated: 1.1.1.1, 1.0.0.1
- Click Apply, then toggle the connection off and on to activate
NetworkManager writes its changes to /etc/NetworkManager/system-connections/. Read the relevant file there to confirm the dns= line was saved correctly under the [ipv4] section.
Method 4: resolvectl — Runtime-Only Changes
Use resolvectl for temporary DNS overrides — testing a new resolver before committing it to Netplan, or forcing a specific DNS for one interface during debugging. These changes survive a service restart but are cleared on reboot or when the interface reconnects.
Replace ens3 with your interface name. The ~. domain hint routes all queries through this interface's DNS. Without it, systemd-resolved may route around your setting for queries that match other configured search domains.
Flush the DNS cache after any change and check statistics:
resolvectl changes are runtime-only. If you reboot and your new DNS is gone, this is why. Always follow up with a Netplan or resolved.conf change to make it permanent.
CLI Verification: Confirming the Right DNS Is Active
Never assume a change worked — verify it. These commands show exactly what is resolving your queries and which upstream server answered:
Cross-check what your configured resolvers return versus the wider internet with the DNS Lookup tool — useful for isolating a caching problem or verifying a new authoritative server is responding correctly before pushing a change to production.
Key Fields in resolvectl status Output
- DNS Servers: should show the IPs you configured under the interface you edited
- Current DNS Server: the upstream server being queried right now
- DNSSEC supported: yes: validation is active if you enabled DNSSEC
- DNS over TLS: yes: TLS encryption to your upstream is negotiated
- Cache hits / misses: visible via resolvectl statistics — a high hit ratio means the cache is working
IPv6 DNS, DNS-over-TLS, and DNSSEC in 2026
Ubuntu 24.04's systemd-resolved ships at version 255+, which includes improvements that are worth enabling for modern deployments.
IPv6 resolvers: Add IPv6 addresses alongside IPv4 in both Netplan and resolved.conf if your upstream supports them. Cloudflare's IPv6 resolvers are 2606:4700:4700::1111 and 2606:4700:4700::1001. Google's are 2001:4860:4860::8888 and 2001:4860:4860::8844. systemd-resolved queries both A and AAAA records simultaneously when IPv6 is available, so listing both address families carries no performance penalty.
DNS-over-TLS strict mode: Setting DNSOverTLS=yes in resolved.conf requires the upstream to present a valid TLS certificate on port 853. Cloudflare (1.1.1.1), Google (8.8.8.8), and Quad9 (9.9.9.9) all support strict DoT. For corporate or internal resolvers, verify port-853 support before enabling — if the server does not respond on 853, strict mode causes all DNS to fail silently with no obvious error message in application logs.
DNSSEC strategy: The allow-downgrade setting is the pragmatic choice for most environments. Strict DNSSEC=true rejects responses from zones with misconfigured signatures, and there are more of those than expected in the wild. If a domain stops resolving after you enable DNSSEC, test it with dig example.com +dnssec and look for the ad flag in the response flags line — its absence confirms a validation failure.
The original DNS specification RFC 1035 is the protocol foundation; RFC 4033 covers DNSSEC and RFC 7858 covers DNS-over-TLS for anyone who wants the authoritative source on how these features interact at the wire level.
Common Misdiagnoses
Editing /etc/resolv.conf directly
The single most common mistake on Ubuntu 24.04. The file is a symlink managed by systemd-resolved. Direct edits are overwritten on the next service restart or network event. Use Netplan or resolved.conf instead.
Adding nameserver lines to /etc/resolvconf/resolv.conf.d/head
The resolvconf package is not installed by default on Ubuntu 24.04, and systemd-resolved ignores it entirely. Lines in that file do nothing unless you have explicitly installed and integrated resolvconf — which then conflicts with systemd-resolved unless the two are configured to coexist.
Change works until the next reboot
You used resolvectl for a runtime change without updating Netplan or resolved.conf. Always persist changes through the configuration layer that owns your interface. resolvectl is for testing, not for production configuration.
App still hitting the old DNS server after an OS-level change
Application-level caching. Chrome and Firefox maintain their own DNS caches independent of the OS resolver. Flush Chrome at chrome://net-internals/#dns and click Clear host cache. Flush Firefox at about:networking#dns. Java applications cache DNS inside the JVM and ignore OS-level flushes entirely — you must restart the JVM process to force a re-lookup.
DNSSEC blocking a legitimate domain
Some domains have misconfigured DNSSEC records that pass the authoritative nameserver but fail validation in a strict resolver. Switch to DNSSEC=allow-downgrade as a first diagnostic step. Then test the specific domain with dig +dnssec +cd @1.1.1.1 thatdomain.com — the +cd flag disables checking so you see the raw signed response and can identify the broken record type.
VPN or Docker overriding your DNS
OpenVPN, WireGuard (via NetworkManager), and Docker all push per-link DNS overrides directly into systemd-resolved. Run resolvectl status and check whether your VPN interface (tun0, wg0, or similar) has its own DNS Servers entry that is winning over your configured upstream. For Docker containers, add a dns key in /etc/docker/daemon.json to set what containers use, independent of the host resolver configuration.
Confirming the Fix and Preventing Recurrence
After applying any method above, run through this checklist before calling it done:
- Run resolvectl status — the DNS Servers line under your interface shows the IPs you configured.
- Run dig @127.0.0.53 google.com +short — returns IP addresses without timeout errors.
- Run dig google.com +short with no explicit server — same result, confirming the stub is using your new upstream.
- Reboot and repeat step 1 — confirms the change survives a full restart.
- If you enabled DNSSEC, run resolvectl query --type=A example.com and look for authenticated: yes in the output.
To prevent configuration drift on servers: keep your Netplan YAML in version control — an Ansible playbook, a Terraform cloud-init block, or at minimum a Git repo. DNS changes made with resolvectl get lost on the next reboot and create hard-to-diagnose inconsistency across a fleet of machines.
To prevent drift on desktops: if NetworkManager keeps reverting your DNS because DHCP pushes new nameservers, set ipv4.ignore-auto-dns yes via nmcli, or add ignore-auto-dns=true under the [ipv4] section in the connection file at /etc/NetworkManager/system-connections/.
For multi-server fleets: a central recursive resolver — Unbound, Pi-hole, or a corporate nameserver — configured in resolved.conf's DNS= line is far easier to maintain than per-server IP lists. Change the central resolver's upstream once and all machines follow without individual reconfiguration.