When systemd‑resolved returns 127.0.0.1 for every host – fixing the search domain order on Ubuntu 24.04

Why systemd‑resolved is giving you 127.0.0.1 for every host

Ubuntu 24.04 ships with systemd‑resolved as the DNS resolver.
If every hostname you look up ends up at 127.0.0.1, the most common culprit is the search‑domain order that resolved builds.
It pulls the list from three places:

  1. /etc/resolv.conf (or the DNS=/Domains= directives in /etc/systemd/resolved.conf)
  2. DHCP‑provided domains
  3. The machine’s own hostname ($HOSTNAME)

When localhost or the local hostname lands at the top, the resolver will try it before forwarding the query to the real DNS servers, and you’ll get a loopback address for any name that isn’t fully qualified.

Below is a practical walk‑through to diagnose and fix the issue, with a focus on sensible, secure defaults.


1. Verify the current state

# Show the effective search list
systemd-resolve --status | grep -A4 'Current DNS Server'

# Quick test
dig +short example.com

If dig spits back 127.0.0.1 for a public domain, the search order is definitely off.


2. Inspect /etc/systemd/resolved.conf

The file is usually empty or just comments. Add explicit DNS servers and a clean search list:

# /etc/systemd/resolved.conf
[Resolve]
DNS=8.8.8.8 8.8.4.4
Domains=~.   # “~” means “prepend the machine’s hostname”
# or, if you prefer a fixed domain:
# Domains=example.com

The tilde (~) tells resolved to prepend the local hostname, but it will still fall back to the global domains you specify.
After editing, reload:

sudo systemctl restart systemd-resolved

3. Make /etc/resolv.conf point to the local stub

Ubuntu 24.04 ships with a symlink:

ls -l /etc/resolv.conf

It should point to /run/systemd/resolve/stub-resolv.conf.
If it points elsewhere, recreate it:

sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

The stub listens on 127.0.0.53 and forwards queries to the servers defined in resolved.conf.
Using the stub keeps the system from leaking the real DNS servers to applications that read /etc/resolv.conf directly.


4. Disable DHCP‑provided domains if they’re wrong

If your network interface receives a domain via DHCP that conflicts with your local hostname, resolved will prepend it.
You can disable this behaviour in resolved.conf:

[Resolve]
# …
# Disable DHCP domains
Domains=~.

Alternatively, edit the DHCP client configuration (e.g., /etc/netplan/*.yaml or /etc/dhcp/dhclient.conf) to drop the domain option.


5. Verify the search order again

systemd-resolve --status | grep -A4 'Current DNS Server'

You should now see something like:

Current DNS Server: 8.8.8.8
Current DNS Server: 8.8.4.4
DNS Server: 8.8.8.8
DNS Server: 8.8.4.4
Search Domain: example.com

Test a few names:

dig +short www.google.com
dig +short mylocalhost

The first should resolve to a public IP, the second to the correct local address.


6. Security considerations

  • Avoid exposing internal DNS servers – the stub keeps internal servers hidden from userland tools that might log /etc/resolv.conf.

  • Use DNS over TLS/HTTPS – systemd‑resolved supports DNSSEC=yes and DNSOverTLS=yes. Add them to resolved.conf:

    [Resolve]
    DNS=1.1.1.1 1.0.0.1
    Domains=~.
    DNSSEC=yes
    DNSOverTLS=yes
    

    This ensures integrity and privacy of DNS queries.

  • Restrict local network access – the stub listens only on 127.0.0.53. If you expose the resolver on a public interface, bind it to a specific address or use firewall rules.


7. Common pitfalls and how to avoid them

SymptomLikely causeFix
dig example.com returns 127.0.0.1/etc/resolv.conf points to /etc/resolv.conf instead of the stubRecreate the symlink to /run/systemd/resolve/stub-resolv.conf
DNS works for FQDNs but not for short namesSearch list starts with localhostAdd Domains=~. to resolved.conf
DNS fails after a DHCP lease renewalDHCP client re‑writes /etc/resolv.confDisable DHCP domains or use Netplan’s nameservers stanza

8. Quick checklist

  1. resolved.conf – set DNS= and Domains=~.
  2. Symlink – /etc/resolv.conf → /run/systemd/resolve/stub-resolv.conf
  3. Restart – sudo systemctl restart systemd-resolved
  4. Test – dig +short example.com
  5. Secure – enable DNSSEC and DNSOverTLS if needed

9. Where to look next

If the problem persists after these steps, check:

  • Netplan (/etc/netplan/*.yaml) – ensure nameservers are not overriding resolved.conf.
  • DHCP client – some setups (e.g., dhclient) may still inject domains.
  • Firewall – make sure 127.0.0.53 is reachable from your applications.


See also