Ubuntu DNS Configuration Guide

Khimananda Oli 7 min read Virtualization
Ubuntu DNS Configuration Guide

By Khimananda Oli | Last reviewed: August 2026

When your Ubuntu server cannot resolve hostnames, application deployments fail, package updates stall, and inter-service communication breaks immediately. This Ubuntu DNS configuration guide provides the exact steps to configure, verify, and troubleshoot name resolution on modern Ubuntu systems using systemd-resolved and Netplan. Whether you are setting up a fresh VPS or debugging a production outage, understanding the resolver stack is non-negotiable infrastructure work. For foundational server hardening before touching networking, review my initial Ubuntu server setup guide.

Application(curl / apt / nginx)getaddrinfo()systemd-resolvedStub Listener127.0.0.53:53Local Cache + DNSSECUpstream DNS8.8.8.8 / 1.1.1.1(Cloud / ISP)Internal DNS10.0.0.2(VPC / AD)
Ubuntu DNS resolution flow: applications query the local systemd-resolved stub, which caches results and forwards misses to configured upstream nameservers.

How does Ubuntu DNS configuration work with systemd-resolved?

Modern Ubuntu releases (22.04 LTS through 24.04 LTS in 2026) use systemd-resolved as the central DNS manager. It replaces direct /etc/resolv.conf editing with a managed stub resolver listening on 127.0.0.53. Applications call standard glibc functions like getaddrinfo(), which the NSS layer redirects to this local stub. The stub maintains a per-interface cache, validates DNSSEC signatures when enabled, and routes queries to the upstream nameservers defined in your Netplan or DHCP configuration.

A common mistake is manually editing /etc/resolv.conf. On a default Ubuntu install, this file is a symlink to /run/systemd/resolve/stub-resolv.conf. Any manual changes vanish after reboot or network restart because systemd-resolved regenerates it. You must configure DNS at the source: either Netplan for static servers or the DHCP client for dynamic environments. Understanding this chain prevents hours of frustrating debugging where settings appear correct but never persist.

For servers running container workloads, note that Docker and Kubernetes often manage their own DNS. If you are deploying microservices, consult the Kubernetes secrets and ConfigMaps guide to understand how cluster DNS interacts with node-level resolution. The host's systemd-resolved still matters for node-level operations like package installation, log shipping agents, and backup scripts.

How do you configure static DNS servers using Netplan?

Netplan is the declarative network configuration tool for Ubuntu. All persistent DNS settings belong here. The configuration lives in /etc/netplan/, typically as 01-netcfg.yaml or 50-cloud-init.yaml on cloud instances. YAML indentation is strict; two spaces per level, no tabs.

Editing the Netplan configuration

  1. Identify your active Netplan file:
    ls /etc/netplan/
  2. Back up the existing config:
    sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.bak
  3. Edit with a safe editor (nano or vim):
    sudo nano /etc/netplan/01-netcfg.yaml
  4. Define your nameservers under the correct interface. A typical static configuration looks like this:
network:
  version: 2
  renderer: networkd
  ethernets:
    ens3:
      addresses:
        - 192.168.1.10/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 8.8.4.4
        search:
          - example.com
          - internal.example.com

The search directive defines domain suffixes appended to unqualified hostnames. If you frequently access db.internal.example.com as just db, add internal.example.com to this list. Order matters: the resolver tries each suffix sequentially.

Validating and applying changes

Always validate syntax before applying. A typo can lock you out of remote servers:

sudo netplan generate
sudo netplan try --timeout 120

The try command applies changes temporarily and reverts them if you don't confirm within the timeout. This is critical for remote servers. Once confirmed working, make permanent with sudo netplan apply. Verify the result:

resolvectl status
cat /run/systemd/resolve/resolv.conf

If you are automating server provisioning across multiple environments, consider integrating this into your IaC workflow. My article on automating server provisioning with cloud-init covers injecting Netplan configs during instance launch, eliminating manual SSH configuration entirely.

Edit YAML/etc/netplan/01-netcfg.yamlBackup first!Generatenetplan generateSyntax checkFails = fix YAMLTry (Safe)netplan tryAuto-revert 120sTest connectivityApplynetplan applyPermanentVerify resolvectlSyntax error
Safe Netplan DNS configuration workflow: always validate with generate and test with try before permanent apply to avoid remote lockout.

How do you troubleshoot Ubuntu DNS resolution failures?

DNS issues manifest as timeouts, NXDOMAIN errors, or incorrect IP returns. Systematic diagnosis saves time. Start with resolvectl query example.com — this bypasses application-layer caching and hits systemd-resolved directly. Compare its output with dig @127.0.0.53 example.com to isolate whether the problem is in the stub resolver or upstream.

Check which upstream servers are active per interface:

resolvectl status | grep "DNS Servers"

If the listed servers differ from your Netplan config, DHCP may be overriding your static settings. On cloud instances, cloud-init often injects DHCP-provided DNS. To prevent this, add dhcp4-overrides: { use-dns: false } under your interface in Netplan. This forces static nameservers even when DHCP is active for addressing.

Cache poisoning or stale entries cause intermittent failures. Flush the local cache without restarting the service:

sudo resolvectl flush-caches
resolvectl statistics

The statistics output shows cache hit rates. A consistently low hit rate suggests either aggressive TTLs from upstream or misconfigured caching. For production systems handling sensitive domains, enable DNSSEC validation by adding DNSSEC=yes to /etc/systemd/resolved.conf and restarting systemd-resolved. This prevents man-in-the-middle attacks on DNS responses, crucial for compliance environments.

When debugging complex multi-service architectures, remember that observability extends to DNS. Tools discussed in the AI-powered log analysis article can correlate DNS failures with application errors, revealing patterns that manual grep misses. Persistent DNS latency often indicates upstream provider issues rather than local misconfiguration.

Should you use systemd-resolved or manage resolv.conf directly?

This decision depends on your operational context. While systemd-resolved is the default and recommended approach for most Ubuntu servers in 2026, specific scenarios justify alternatives. Legacy applications expecting a traditional /etc/resolv.conf with direct nameserver lines may malfunction with the stub resolver. Container hosts running Docker with custom DNS plugins sometimes conflict with systemd-resolved's port 53 binding.

Criteriasystemd-resolved (Default)Static resolv.conf
PersistenceManaged via Netplan/systemdManual or scripted
CachingBuilt-in per-interfaceNone (requires nscd/dnsmasq)
DNSSECNative supportRequires external validator
Per-interface routingYes (split-DNS capable)No (global only)
Legacy compatibilityGood (via NSS)Universal
ComplexityModerate learning curveSimple but fragile
Best forModern servers, laptops, K8s nodesContainers, legacy apps, minimal images

To disable systemd-resolved and use static resolv.conf:

sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf

The chattr +i makes the file immutable, preventing accidental overwrites. Remove immutability with chattr -i before future edits. This approach sacrifices caching and DNSSEC but eliminates the stub resolver entirely. I recommend this only when you have a documented reason; for 95% of Ubuntu servers in 2026, systemd-resolved with proper Netplan configuration is the correct choice.

systemd-resolvedApp (glibc)getaddrinfo()Stub Resolver127.0.0.53:53Cache LayerPer-interface TTLDNSSECValidationUpstream DNS8.8.8.8 / InternalStatic resolv.confApp (glibc)getaddrinfo()/etc/resolv.confnameserver X.X.X.XUpstream DNSDirect queryNo cache · No DNSSEC · Manual mgmtUse only for containers / legacy apps
Architecture comparison: systemd-resolved provides caching, DNSSEC, and per-interface routing versus the simpler but limited static resolv.conf approach.

Reliable Ubuntu DNS Configuration for Production

Getting DNS right on Ubuntu means respecting the systemd-resolved and Netplan stack instead of fighting it. Define nameservers declaratively in Netplan, validate with netplan try, verify with resolvectl status, and monitor cache statistics in production. Disable the stub resolver only when you have a concrete incompatibility, not out of habit. This Ubuntu DNS configuration guide reflects the patterns I use across client infrastructure in 2026 — tested on hundreds of servers from Kathmandu data centers to AWS us-east-1.

If your team needs help auditing DNS architecture, implementing split-horizon resolution for hybrid clouds, or preparing networking documentation for SOC 2 compliance, reach out through my contact page. Reliable name resolution is invisible when it works and catastrophic when it doesn't — let's make sure yours is in the former category.

Frequently Asked Questions

Edit /etc/netplan/01-netcfg.yaml, add nameservers under your interface, then run sudo netplan apply to activate changes immediately.

Modern Ubuntu uses Netplan YAML files in /etc/netplan/ rather than editing /etc/resolv.conf directly, as systemd-resolved manages that symlink dynamically.

Direct edits to /etc/resolv.conf are overwritten by systemd-resolved; configure persistent nameservers via Netplan or use resolvectl instead.

Run resolvectl status to display active interfaces, current DNS servers, and search domains configured by systemd-resolved without parsing config files.

Systemd-resolved provides local caching and DNSSEC validation natively, while dnsmasq offers advanced DHCP integration and split-horizon DNS for complex networks.

Stop and mask systemd-resolved.service, remove the /etc/resolv.conf symlink, then create a static file pointing to your preferred upstream resolver.

Yes, set DNSOverTLS=yes in /etc/systemd/resolved.conf and specify TLS-capable resolvers like Cloudflare or Quad9 in your Netplan configuration.

Execute sudo resolvectl flush-caches to clear all cached entries instantly, then verify with statistics output showing zero current cache size.

Use dig or resolvectl query instead, as they respect systemd-resolved settings and provide accurate results matching actual system resolution behavior.

Add routing-domains prefixed with tilde in Netplan nameservers section to direct queries for specific zones to designated internal DNS servers only.

Misconfigured IPv6 DNS or unreachable default resolvers cause timeouts; disable IPv6 DNS or explicitly set working IPv4 nameservers in Netplan configuration.

Run resolvectl query example.com and check the authenticated field; if false, enable DNSSEC=yes in resolved.conf and restart the service.

Install bind9 or unbound, configure forwarders to upstream resolvers, and point client machines to this Ubuntu server via DHCP options.

Create /etc/docker/daemon.json with dns array containing your desired nameservers, then restart docker.service to apply container-wide resolution settings.

Root access via sudo is required for editing Netplan configs, restarting systemd-resolved, or modifying /etc/systemd/resolved.conf settings securely.