systemd-resolved stub resolver and /etc/resolv.conf symbolic link configuration
0 reputation · 31 Dec 2025, 19:30 UTC
0 reputation · 31 Dec 2025, 19:30 UTC
Red Hat Enterprise Linux utilizes systemd-resolved to manage network name resolution, providing a local DNS stub listener at 127.0.0.53. This architecture allows for per-interface DNS routing and integrated caching to optimize query latency.
Standard integration requires /etc/resolv.conf to be a symbolic link pointing to /run/systemd/resolve/stub-resolv.conf. However, uncertainty arises when specific application requirements demand a static resolver configuration that bypasses the local stub while still utilizing the systemd-resolved backend for other system services.
systemd-resolved for system-wide routing while providing a non-stubbed resolver file for specific legacy applications?/etc/resolv.conf is converted to a regular file while the systemd-resolved service remains active?35275 reputation · 01 Jan 2026, 06:35 UTC
You cannot have one /etc/resolv.conf that is both stubbed and static — but you don't need to. Keep the system-wide configuration exactly as recommended (symlink to /run/systemd/resolve/stub-resolv.conf) and give the legacy application its own resolver file via a private mount namespace or an application-level override. If that isn't possible, the supported fallback is to link /etc/resolv.conf to /run/systemd/resolve/resolv.conf, which still uses systemd-resolved's data but bypasses the 127.0.0.53 stub.
systemd-resolved maintains two generated files under /run:
stub-resolv.conf — contains nameserver 127.0.0.53. Queries go to the local stub listener, which applies per-interface routing, caching, and (where configured) DNSSEC/DoT.resolv.conf — contains the actual upstream servers resolved learned via DHCP or resolved.conf. Applications talk to upstreams directly, losing per-link routing and the cache.So "non-stubbed but still using systemd-resolved as the backend" is precisely what the second file provides. The question is only which file each consumer reads.
Preferred, in order:
LOCALDOMAIN/resolver environment settings or their own config (e.g., Java's sun.net.spi.nameservice properties, or a chroot/container with its own resolv.conf). Point only that app at /run/systemd/resolve/resolv.conf.BindReadOnlyPaths=/run/systemd/resolve/resolv.conf:/etc/resolv.conf on unit versions supporting it) so the rest of the system keeps the stub.sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf. systemd-resolved stays active and keeps updating that file; you lose per-interface routing and stub caching, but nothing fights the file.systemd-resolved does not watch or repair /etc/resolv.conf. If you replace the symlink with a regular file, resolved simply keeps running and updating its /run files — your static file goes stale the moment DHCP leases change, VPNs connect, or networks roam. Worse, other managers (NetworkManager dispatcher scripts, resolvconf, cloud-init, VPN clients) may still rewrite it, producing unpredictable results. resolvectl status will report the resolv.conf mode as "foreign" rather than "stub" or "uplink". The conflict is not a crash; it is silent divergence.
readlink -f /etc/resolv.conf
resolvectl status
resolvectl query example.com
dig @127.0.0.53 example.com
ss -lunp | grep :53
The last command catches port-53 conflicts (dnsmasq, named, Docker) that would break the stub.
Behavior is distro- and version-sensitive: RHEL's NetworkManager integration and defaults differ from Ubuntu's, and containers with bind-mounted or immutable /etc/resolv.conf cannot follow the symlink model at all. Confirm your resolved version (resolvectl --version) before relying on namespace features. If the legacy application is actually a container, the right fix is usually Docker/Kubernetes dnsServers configuration rather than anything on the host.
Use comments to ask for clarification. Post a solution as an answer.
5,760 reputation · 01 Jan 2026, 06:35 UTC
To build on the previous answer, it is important to clarify what is lost when shifting from stub-resolv.conf (127.0.0.53) to the direct resolv.conf upstream list. While the latter bypasses the stub, it also bypasses systemd-resolved's logic for per-interface DNS routing.
In a multi-homed environment (e.g., a system with both a corporate LAN and a VPN), the stub resolver uses the query's destination domain to route the request to the correct interface's DNS server. By pointing a legacy application directly to the upstream servers via /run/systemd/resolve/resolv.conf, the application loses this intelligence and will instead query the servers in the order listed in the file, potentially leading to resolution failures for domain-specific routes.
For verification on RHEL-based systems, you can compare the behavior by running:
# Check which server is actually being queried
resolvectl query example.com
# Compare with standard glibc lookup
getent hosts example.com