
AVAHI vs systemd-resolved: can they coexist, and what breaks if both try to handle mDNS/DNS-SD?
On a modern Linux system, AVAHI and systemd-resolved can absolutely coexist—but only if you draw a very clear line between which component owns mDNS/DNS-SD and how name resolution flows through nsswitch. If you let both try to “help” with multicast DNS at the same time, you don’t usually get more reliability; you get split-brain behavior, intermittent failures, and tools that only work sometimes.
Quick Answer: The safest overall choice for mDNS/DNS-SD on Linux desktops and small LANs is Avahi + nss-mdns. If your priority is centralizing all name resolution into systemd’s stack, systemd-resolved is often a stronger fit. For tightly controlled environments where you only need *.local resolution and no D-Bus browsing, consider systemd-resolved with Avahi limited to service publication only.
At-a-Glance Comparison
| Rank | Option | Best For | Primary Strength | Watch Out For |
|---|---|---|---|---|
| 1 | Avahi + nss-mdns | Full mDNS/DNS-SD on Linux (Bonjour/Zeroconf-style) | Mature, Linux-first mDNS/DNS-SD daemon with D-Bus API and XML service files | Must ensure systemd-resolved is not also trying to own mDNS on the same interfaces |
| 2 | systemd-resolved (mDNS enabled) | Centralized resolver stack with basic mDNS | Single resolver for unicast DNS + mDNS, integrated with systemd | Lacks Avahi’s D-Bus service-browse/publish model; fewer consumers expect this API |
| 3 | Hybrid: systemd-resolved for DNS, Avahi for DNS-SD | Controlled setups that want Avahi’s DNS-SD but keep systemd-resolved for DNS | Keeps unicast DNS with systemd-resolved while Avahi handles DNS-SD via D-Bus | Easy to misconfigure nsswitch and *.local handling; debugging split behavior can be painful |
Comparison Criteria
We evaluated each setup based on three practical criteria:
-
mDNS/DNS-SD feature coverage:
Whether the stack exposes not just *.local name resolution but also real DNS-SD browsing and service publication (printers, file shares, peer apps). -
Integration surfaces & ecosystem compatibility:
How well each option lines up with the way existing Linux software expects to talk to service discovery: D-Bus, XML under/etc/avahi/services, compatibility shims (Bonjour/Zeroconf), andnsswitch. -
Operational clarity when coexisting:
How easy it is to reason about “who owns what” when both Avahi and systemd-resolved are installed—especially around *.local resolution, interface binding, and debugging failures.
Detailed Breakdown
1. Avahi + nss-mdns (Best overall for full mDNS/DNS-SD on Linux)
Avahi + nss-mdns ranks as the top choice because it implements a full mDNS/DNS-SD stack with well-defined integration paths (D-Bus and /etc/avahi/services) and a clear story for *.local hostname resolution via nsswitch.
What it does well:
-
Full mDNS/DNS-SD with Bonjour/Zeroconf-style behavior:
Avahi is explicitly “a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite.”
Practically, that means:- Browsing services over D-Bus (e.g., find printers to print to, find files being shared).
- Publishing services dynamically over D-Bus or statically via XML definitions in
/etc/avahi/services. - Interoperating with Apple devices that speak Bonjour/Zeroconf.
-
Clear integration model for applications and distros:
Avahi exposes:- A D-Bus API (primary API; required for most usage) for browsing/advertising services.
- An XML-based static publisher via
/etc/avahi/servicesso you can advertise services without writing a publisher. - Compatibility libraries (
avahi-compat-libdns_sd,avahi-compat-howl) so software written for Bonjour or HOWL can work unchanged.
For name resolution, the nss-mdns project “allows hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch.” That’s what makes
ping host.localand random CLI tools work.
Tradeoffs & Limitations:
- You must keep systemd-resolved’s mDNS role in check:
Avahi itself focuses on mDNS/DNS-SD; it doesn’t own unicast DNS. On modern systemd-based distributions, systemd-resolved is often the default stub resolver. If you also let systemd-resolved do mDNS on the same interfaces, you risk:- Competing responses on the mDNS multicast group.
- Confusing
nsswitchconfiguration where some tools hit nss-mdns → Avahi and others go via systemd-resolved. - Hard-to-reproduce “works in GUI app, fails in CLI” cases.
Decision Trigger:
Choose Avahi + nss-mdns if you want a complete mDNS/DNS-SD implementation and prioritize interoperability and established Linux integration (D-Bus, /etc/avahi/services, nsswitch). This is usually the right choice for desktops, laptops, and small LANs where “find printers and shared files” is the goal.
2. systemd-resolved (Best for unified resolver stack with basic mDNS)
systemd-resolved is the strongest fit when your priority is to centralize all name resolution—unicast DNS, DNS-over-TLS, and mDNS—under one daemon, rather than running a dedicated mDNS/DNS-SD system like Avahi.
What it does well:
-
Single resolver for regular DNS and mDNS:
In a typical modern systemd setup, systemd-resolved:- Acts as a stub resolver on
127.0.0.53. - Handles upstream DNS, DNSSEC, DNS-over-TLS, and DNS configuration from systemd-networkd/NetworkManager.
- Can be configured to do mDNS lookups for
.local.
This simplifies the mental model: all name resolution goes through a single path.
- Acts as a stub resolver on
-
Tight integration with systemd tooling: You manage it with familiar systemd interfaces (
systemctl,resolvectl). For admins already wiring everything through systemd, that’s operationally convenient.
Tradeoffs & Limitations:
-
Not a drop-in replacement for Avahi’s DNS-SD model:
Avahi is centered around mDNS/DNS-SD as a system component with:- A D-Bus API for service browsing/registration.
- Static service definitions via
/etc/avahi/services. - Compatibility for Bonjour’s
dns_sd.hAPI.
Many desktop and LAN-aware applications are built to talk to Avahi (via D-Bus or Bonjour-compatibility), not directly to systemd-resolved. If you remove Avahi entirely:
- Existing consumers expecting Avahi’s D-Bus API will lose service discovery.
- You’ll have *.local resolution but not the rich DNS-SD browsing Avahi provides.
Decision Trigger:
Choose systemd-resolved with mDNS enabled and Avahi disabled if you value a single resolver stack over full DNS-SD capabilities, and your application set doesn’t depend on Avahi’s D-Bus or Bonjour compatibility. This tends to make sense on minimal servers or appliances that just need *.local name resolution.
3. Hybrid: systemd-resolved for DNS, Avahi for DNS-SD (Best for controlled, niche setups)
The hybrid setup stands out when you want systemd-resolved to keep handling unicast DNS, but still rely on Avahi’s D-Bus/DNS-SD model for service discovery. In practice, this is what many distributions ship: systemd-resolved as the resolver, Avahi as the mDNS/DNS-SD daemon, and nss-mdns bridging *.local into nsswitch.
What it does well:
-
Keeps unicast DNS and systemd features while preserving Avahi APIs:
In this model:- systemd-resolved is still your stub resolver for “regular” DNS lookups.
- Avahi runs as the mDNS/DNS-SD daemon (Bonjour/Zeroconf-compatible).
- nss-mdns is used in
/etc/nsswitch.confto send *.local resolution to Avahi.
Applications continue to use Avahi’s D-Bus or compat libraries for browsing and publishing services, while the OS still enjoys systemd-resolved’s DNS plumbing.
-
Closer to what many Linux ecosystems expect:
This setup matches the reality that “Avahi is primarily targeted at Linux systems and ships by default in most distributions.” Many desktop stacks simply assume an Avahi daemon is present.
Tradeoffs & Limitations:
-
*Easy to misconfigure .local handling between the two daemons:
The risk in a hybrid setup is letting systemd-resolved also decide it should speak mDNS on.localwhile nss-mdns sends the same traffic to Avahi. When that happens, things break in non-obvious ways:- Some tools resolve
hostname.localvia nss-mdns → Avahi. - Others go via glibc → systemd-resolved directly and get different behavior.
- You may see intermittent or interface-dependent resolution failures.
You have to be deliberate about:
- How
/etc/nsswitch.confis ordered (wheremdns/mdns_minimal/resolveappear). - Whether systemd-resolved’s mDNS support is enabled or disabled on specific links.
- Avoiding two active mDNS responders trying to own the same hostname.
- Some tools resolve
Decision Trigger:
Choose systemd-resolved for DNS + Avahi for DNS-SD if you want to keep systemd-resolved as the unicast DNS resolver but still rely on Avahi’s mature DNS-SD interfaces (D-Bus, /etc/avahi/services) and Bonjour compatibility. This is appropriate for distributions and environments that can enforce a sane nsswitch and link configuration.
Can Avahi and systemd-resolved coexist?
Yes, they can coexist. The key is making sure only one component is responsible for each function:
-
mDNS/DNS-SD advertising and browsing:
Hand this to Avahi. That’s its whole job:- It runs a dedicated mDNS/DNS-SD stack.
- It exposes a D-Bus API and
/etc/avahi/services. - It provides Bonjour/Zeroconf interoperability.
-
Unicast DNS and general resolver duties:
Let systemd-resolved own this (if your distro uses it):- Stub resolver on
127.0.0.53. - Upstream DNS, DNSSEC, DNS-over-TLS, etc.
- Stub resolver on
-
*.local hostname resolution via system programs:
Point this through nss-mdns → Avahi, not directly to systemd-resolved, if Avahi is your mDNS daemon.nss-mdnsis explicitly “for hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch.”
In that arrangement, Avahi and systemd-resolved live side by side, each handling their own scope without contention.
What breaks if both try to handle mDNS/DNS-SD?
If you leave both Avahi and systemd-resolved trying to own mDNS/DNS-SD on the same host and interfaces, you tend to see these classes of problems:
1. Split-brain *.local resolution
Symptoms:
ping host.localworks from one terminal but fails from another tool.- GUI apps see printers and shares, but CLI tools don’t—or vice versa.
- You get inconsistent responses for the same hostname depending on call path.
Why it happens:
- Some lookups flow through
glibc -> nsswitch -> nss-mdns -> Avahi. - Others flow through
glibc -> systemd-resolveddirectly (e.g., via the stub resolver). - Both daemons are listening on the mDNS multicast group; they may respond differently or at different times.
Result: name resolution becomes non-deterministic from the user’s perspective.
2. mDNS hostname conflicts and flapping
If both daemons try to claim the same .local hostname:
- You can see:
- “Name in use” behavior or retries.
- Hostnames that appear and disappear from the network as conflict detection kicks in.
- Remote Bonjour/Zeroconf clients may:
- See duplicate or conflicting entries.
- Randomly pick one, or ignore the host if they detect weirdness.
With mDNS, having multiple stacks on one host is generally discouraged; Avahi’s own docs advise against embedding multiple mDNS stacks on the same system.
3. DNS-SD browsing and publishing failures
Avahi is designed around D-Bus-based DNS-SD:
- Applications often call:
- Avahi’s D-Bus interface directly.
- Or Bonjour-compatible APIs via
avahi-compat-libdns_sd.
If you try to lean on systemd-resolved for mDNS/DNS-SD but still have Avahi installed:
- Some apps will still talk to Avahi and expect it to be authoritative.
- Others may indirectly trigger systemd-resolved’s mDNS via name lookups.
- You end up with two partial views of the service set on the LAN.
Result: you can see “missing services” in one app but not another, or services advertised via one stack that aren’t discoverable via the other.
4. Debugging becomes unpleasant
When “hostname.local doesn’t resolve”:
- With a single mDNS stack, you can:
- Check Avahi status (
systemctl status avahi-daemon). - Inspect services in
/etc/avahi/services. - Confirm
nsswitchand nss-mdns configuration.
- Check Avahi status (
- With two stacks:
- You’re guessing which daemon a given tool is actually hitting.
resolvectlmay show one picture; Avahi browsers show another.- Race conditions and subtle timing issues surface, similar in spirit to the “racing signals with D-Bus object creation” bugs you see when multiple components fight over the same interface.
The net effect is that the failure mode stops being “it never works” and becomes “it sometimes works,” which is far worse in production.
Practical coexistence patterns
If you’re maintaining a distro image or fleet, these are the practical patterns I’d recommend:
-
Desktop / laptop with rich LAN discovery:
- Enable Avahi + nss-mdns for mDNS/DNS-SD.
- Use systemd-resolved for unicast DNS only (disable its mDNS on links where Avahi operates).
- Ensure
/etc/nsswitch.confsends.localtomdns/mdns_minimalbeforeresolve.
-
*Minimal server that only needs .local resolution, no DNS-SD:
- Disable Avahi entirely.
- Let systemd-resolved handle mDNS for
.local. - Keep
nsswitchsimple (hosts: files resolve dnsor distro default).
-
Mixed environment where you need Avahi’s D-Bus API but also rely heavily on systemd-resolved:
- Run Avahi for mDNS/DNS-SD.
- Keep systemd-resolved for unicast DNS.
- Be strict about:
- Disabling mDNS in systemd-resolved on interfaces where Avahi operates, or
- Ensuring all mDNS requests go via nss-mdns → Avahi, not systemd-resolved.
Final Verdict
Avahi and systemd-resolved can coexist cleanly, but they should not both simultaneously “own” mDNS/DNS-SD on the same host. For most Linux-first, Bonjour/Zeroconf-style service discovery use cases, running Avahi as the sole mDNS/DNS-SD daemon and wiring *.local lookups through nss-mdns via nsswitch is the most predictable, interoperable setup. systemd-resolved fits best as the general DNS resolver and, in environments that don’t need full DNS-SD, as a simple mDNS provider once Avahi is removed.
If you find yourself debugging inconsistent hostname.local behavior or missing printers/shares, the first step is to decide which daemon is responsible for mDNS/DNS-SD, commit to that choice, and configure the other to stay out of the multicast path.