Diagnose and Tune DNS with resolvectl
You will finish with a practical DNS workflow for a Linux host running systemd-resolved: inspect the active links and servers, test normal and specific record lookups, watch local resolver traffic, and make a temporary per-interface change with a clear undo command. The examples match the installed systemd-resolved package, version 255.4-1ubuntu8.17, whose resolvectl reports systemd version 255.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell and a host using systemd-resolved. The inspection commands are ordinary user commands. Configuration changes and counter resets may need sudo, depending on the host's policy. No command below edits a configuration file directly.
1. Check the resolver that is actually in use
Start with the version and global status. This separates an option mismatch from a DNS problem and shows whether the host is using a stub resolver, per-link DNS, DNSSEC, LLMNR or MulticastDNS:
$ resolvectl --version
systemd 255 (255.4-1ubuntu8.17)
$ resolvectl status --no-pager
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp0s31f6)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 185.12.64.2
DNS Servers: 185.12.64.1 185.12.64.2
Your interface and addresses will differ. The useful checkpoint is a link with a DNS scope and at least one server. If every link has Current Scopes: none, resolving names will fail until network configuration supplies a suitable DNS path.
2. Test ordinary forward and reverse lookups
Use query for the normal client-facing test. A hostname returns IPv4 and IPv6 addresses by default; an address performs a reverse lookup:
$ resolvectl query localhost
localhost: 127.0.0.1 -- link: lo
::1 -- link: lo
-- Information acquired via protocol DNS ...
-- Data is authenticated: yes; Data was acquired via local or encrypted transport: yes
-- Data from: synthetic
The timing and spacing vary, but the installed command identifies the answer's source in the final metadata. A result can be synthetic, cached, obtained through a particular link, or authenticated by DNSSEC. For a narrow family test, use one of these ordinary, read-only commands:
$ resolvectl -4 query example.com
$ resolvectl -6 query example.com
$ resolvectl query 127.0.0.1
Single-label names may be expanded through configured search domains. That search behaviour is disabled when you request a record type or class, so a low-level test should use a fully qualified name.
3. Ask for a specific DNS record
Combine query with --type when the question is about a resource record rather than general address resolution. The class defaults to IN:
$ resolvectl --legend=no --type=MX query example.com
Expect one or more lines identifying the queried name, class and MX records, or an error if the name has no such record. Replace the domain with one you administer or are authorised to inspect. Other useful types include A, AAAA, TXT, SRV and CAA. With --type or --class, search-domain expansion and automatic IDNA translation are disabled. That is deliberate: the argument is treated as the exact DNS name you supplied.
For a service lookup, use the service name and domain as separate arguments:
$ resolvectl service _sip._tcp.example.com
An empty answer is not proof that the resolver is broken. It may mean the record does not exist, the selected protocol cannot reach the relevant scope, or the service publishes a different name.
4. Watch what local applications ask for
When a program reports intermittent DNS failures, run the monitor in one terminal:
$ resolvectl monitor
As local clients make requests, the command prints each lookup key and the resource records returned. In a second terminal, reproduce the failing action. Stop the monitor with Ctrl-C. It shows queries issued by local clients, not a packet-for-packet transcript of requests sent to upstream servers. A cache hit, DNSSEC validation or a CNAME chain can change what appears. Do not leave this running on a shared terminal: hostnames requested by local applications can disclose useful operational information.
For a point-in-time view, resolvectl statistics reports resolver and DNSSEC counters. resolvectl show-cache is available in version 255 and can show cache contents. These are observations, not proof that a particular application used a particular server.
5. Make a temporary per-link DNS change
Only do this when you have the interface name and an approved DNS server. This changes the running resolver state and can disrupt name resolution for other programs. Record the current state with resolvectl status first, and keep the recovery command ready:
$ resolvectl status --no-pager
$ sudo resolvectl dns enp0s31f6 192.0.2.53
$ resolvectl status enp0s31f6 --no-pager
192.0.2.53 is documentation space. Substitute a real, approved server and your real link. The command registers per-interface data with systemd-resolved; it does not rewrite your network manager's persistent profile. A network manager may later replace this setting.
To remove the temporary per-interface settings and return that link to its defaults, use the documented undo operation:
$ sudo resolvectl revert enp0s31f6
$ resolvectl status enp0s31f6 --no-pager
revert also undoes that link's search and route-only domains, default-route decision, LLMNR, mDNS, DNSSEC and DNS-over-TLS settings made through resolvectl. If the interface disappears, its runtime configuration is lost automatically.
6. Clear caches only when the symptom justifies it
Use cache flushing as a diagnostic step, not as a ritual:
$ sudo resolvectl flush-caches
$ resolvectl statistics
This discards locally maintained DNS resource-record caches. The next lookup may be slower and will ask the configured resolver again. It does not repair incorrect upstream records, change DNS servers or fix a broken network route. reset-server-features is a separate operation that makes server feature probing start again; use it only when a server capability negotiation is the suspected fault.
reset-statistics resets the counters and requires root. Capture the current statistics first if you need a before-and-after comparison. There is no useful undo for either reset, because discarded counters and cache entries cannot be reconstructed.
Compatibility with resolvconf
The same binary can run in limited compatibility mode when invoked as resolvconf, usually through a symbolic link. Its backend is only systemd-resolved. In that mode, -a reads resolver-compatible input from standard input for a named interface, and -d removes that interface's data. Several options accepted by other implementations are ignored or rejected.
Do not assume that adding a server updates every application. /etc/resolv.conf is updated by this compatibility path only when it is a symlink to /run/systemd/resolve/resolv.conf, not when it is a static file. Inspect the link before changing anything:
$ readlink -f /etc/resolv.conf
/run/systemd/resolve/stub-resolv.conf
The target can legitimately be the stub file rather than the compatibility target. That is a clue about the host's resolver design, not an instruction to replace the symlink.
Done means
resolvectl statusidentifies an active DNS scope and its effective servers.- A normal query succeeds, and you know whether the answer was cached, synthetic or authenticated.
- You can test a precise record without accidentally using search-domain expansion.
monitorhelped correlate a local application's request with the reported failure.- Any temporary per-link change has been reverted, or its owner and recovery command are recorded.
- You flushed caches or reset counters only when the diagnostic goal justified losing that state.