
How do I make hostname.local resolve on Linux using AVAHI + nss-mdns (exact nsswitch.conf lines and packages)?
Most Linux systems ship with Avahi out of the box, but hostname.local still fails to resolve in random CLI tools until nss-mdns is wired into nsswitch.conf. The goal is simple: make foo.local resolve everywhere (shell, SSH, curl, GUI apps) using mDNS/DNS-SD, without special configuration per application.
Below is a practical, distro-oriented walkthrough: which packages to install, the exact nsswitch.conf lines, how to test, and what to watch out for.
All examples assume:
avahi-daemonis running on your LAN- You want Bonjour/Zeroconf-style
*.localresolution- You’re using nsswitch (glibc-style name service switch), which is the standard on mainstream Linux
What you need: Avahi + nss-mdns + nsswitch
At the protocol level:
- Avahi implements mDNS/DNS-SD (Bonjour/Zeroconf-compatible) on your local network.
- nss-mdns plugs mDNS lookups into nsswitch, so
*.localhostnames resolve in “all system programs using nsswitch”.
Mechanically:
- Avahi listens on multicast (
224.0.0.251:5353/ff02::fb:5353) and answers.localqueries. - nss-mdns is configured in
/etc/nsswitch.confso glibc asks Avahi (via mDNS) when resolving*.local. - Applications continue to use standard libc calls (
getaddrinfo,gethostbyname) and seehostname.local“just work”.
You do not talk to Avahi directly from most apps; you wire the libc name resolution path correctly once, and everything benefits.
Step 1: Install the required packages
Package names vary a bit by distribution, but you always need:
- avahi-daemon (and base Avahi libs)
- nss-mdns (the nsswitch plugin for mDNS)
Debian / Ubuntu
sudo apt update
sudo apt install avahi-daemon avahi-utils libnss-mdns
Typical services:
sudo systemctl enable --now avahi-daemon
Fedora / RHEL / CentOS / Alma / Rocky
sudo dnf install avahi avahi-tools nss-mdns
sudo systemctl enable --now avahi-daemon
Arch Linux / Manjaro
sudo pacman -S avahi nss-mdns
sudo systemctl enable --now avahi-daemon
openSUSE
sudo zypper install avahi nss-mdns
sudo systemctl enable --now avahi-daemon
If your distro doesn’t have nss-mdns packaged, check:
and your distribution’s documentation; some BSD-like systems package it slightly differently.
Once packages are installed and avahi-daemon is running, move on to nsswitch.conf.
Step 2: Edit /etc/nsswitch.conf for mDNS
The key is the hosts: line in /etc/nsswitch.conf. This defines the order and mechanisms glibc uses to resolve hostnames.
You want:
/etc/hostsstill honored- local DNS still used
- mDNS (
*.local) handled via nss-mdns - an order that doesn’t break VPNs and corporate DNS
Below are sane patterns that work in real fleets. Use one pattern, not all of them.
Common baseline: glibc-style layout
A typical stock line looks like:
hosts: files dns
You’re going to insert mdns_minimal (or mdns4_minimal, depending on your IPv4/IPv6 policy) before dns, with the [NOTFOUND=return] control to avoid unnecessary DNS lookups when mDNS fails.
Option A (IPv4 only mDNS, recommended for many setups)
hosts: files mdns4_minimal [NOTFOUND=return] dns
files—/etc/hostsmdns4_minimal— mDNS for IPv4, optimized for*.local[NOTFOUND=return]— if mDNS says “no such name”, stop; don’t query DNSdns— regular unicast DNS (corporate DNS, upstream resolver, etc.)
Use this if your mDNS use is IPv4-only or your environment is mostly IPv4.
Option B (IPv4 + IPv6 mDNS)
hosts: files mdns_minimal [NOTFOUND=return] dns
mdns_minimal— mDNS for both IPv4 and IPv6- Rest is the same logic as Option A.
Use this if you care about IPv6 *.local on the LAN.
Option C (mDNS as a fallback)
If you want DNS to be tried first for non-.local names (e.g., to avoid weirdness with internal split-horizon DNS) and only use mDNS as a fallback for .local, you can place it later:
hosts: files dns mdns4_minimal
In this setup:
*.localstill get answered by mDNS (because nss-mdns intercepts them),- But your DNS-first logic remains intact for everything else.
This is less aggressive than the [NOTFOUND=return] pattern and can be safer in some corporate networks.
Important: Do not add both mdns and mdns4_minimal at once unless you know why; it tends to create redundant lookups and confusing behavior. Pick the minimal plugin that matches your needs.
After editing, save /etc/nsswitch.conf. Changes take effect immediately for new processes.
Step 3: Confirm Avahi and nss-mdns are active
Before testing name resolution broadly, verify that:
- Avahi is running
systemctl status avahi-daemon
You want it active (running).
You can also browse services to ensure the mDNS stack is working:
avahi-browse -a
You should see _ipp._tcp, _smb._tcp, etc., if devices are advertising.
- nss-mdns is loaded by glibc
On some systems you can inspect /lib*/libnss_mdns*.so* and ensure they exist:
ls /lib*/libnss_mdns*.so*
If libnss_mdns.so.2 or similar isn’t present, the nss-mdns package may not be installed correctly.
- nsswitch.conf is syntactically valid
A typo in nsswitch.conf can break all host lookups. Make sure the hosts: line is on one line and correctly spaced. getent is a good smoke test:
getent hosts localhost
If this hangs or fails, fix nsswitch.conf before proceeding.
Step 4: Test hostname.local from the client
From another machine on the same LAN (with Avahi + nss-mdns configured as above), test:
getent hosts hostname.local
You should see something like:
192.168.1.42 hostname.local
If that works, libc resolution via nsswitch is in place and:
ssh hostname.localping hostname.localcurl http://hostname.local/
should all work, assuming the remote host is reachable and has services listening.
You can also use ping directly:
ping -c 3 hostname.local
If ping resolves but getent does not, check that ping is using glibc name resolution and not hardwired behavior (on standard Linux it should go through glibc).
Step 5: Ensure the advertising side is correct
For a hostname like hostname.local to resolve:
- The host itself must be running
avahi-daemon. - It must either:
- Let Avahi publish its host name automatically, or
- Publish services via D-Bus or
/etc/avahi/services/*.servicefiles (for service discovery, not strictly needed just for hostname resolution).
On the advertising host, check:
hostname
hostnamectl
By default, Avahi derives its advertised hostname from the system hostname. You can inspect what Avahi thinks via:
avahi-resolve-host-name hostname.local
Ran locally, this should resolve to the host’s own IP.
Also check for collisions — if another device already owns hostname.local on the LAN, Avahi will auto-rename (e.g., hostname-2.local).
Common failure modes and fixes
hostname.local works in some tools but not others
If ssh or curl resolve hostname.local but some other CLI tool does not, verify the process is using the system’s glibc resolver:
- Containerized or statically linked binaries may ignore host nsswitch.
- BusyBox or musl-linked tools may use different resolution rules.
For system programs, corrected /etc/nsswitch.conf plus nss-mdns should be enough.
Works on one distro, not on another
Each distribution ships slightly different defaults for nsswitch.conf. If your hosts differ:
- Align the
hosts:line across them. - Ensure
nss-mdnsis installed on all machines that need to resolve.local.
Remember: only the resolvers need nss-mdns. Only the advertising hosts need avahi-daemon. In a peer mesh, both sides usually run both.
VPN or corporate DNS conflicts
Some VPN clients or resolvconf hooks aggressively rewrite nsswitch.conf or resolv.conf. If *.local suddenly stops resolving when a VPN is up:
-
Re-check
/etc/nsswitch.conf; VPN tooling may have reset thehosts:line. -
Prefer the more conservative pattern:
hosts: files dns mdns4_minimalso DNS remains primary for non-
.localdomains.
.local used by corporate DNS
If your corporate environment wrongly uses .local as an internal DNS zone, you have a naming collision between DNS and mDNS:
- mDNS is standardized for
.local. - Internal DNS zones should avoid
.local.
You’ll need a policy decision: either rely on DNS for that domain and drop nss-mdns usage for .local, or migrate internal naming away from .local. There’s no clean technical fix if both are heavily used.
Why nss-mdns is the “missing piece”
Avahi provides the service discovery plumbing (mDNS/DNS-SD, D-Bus API, /etc/avahi/services XML for static services). But without nss-mdns:
hostname.localresolution is not integrated with glibc’s resolver.- Only Avahi-aware tools (or apps using the D-Bus API directly) can see those names.
By adding nss-mdns to nsswitch.conf, you get:
*.localhostname lookup via mDNS in all system programs using nsswitch- Bonjour/Zeroconf behavior that matches Apple macOS and other Zeroconf environments.
In practice, that’s how you reach the “plug into a network and just find printers and file shares by hostname.local” baseline that users expect.
Final verification checklist
On a working system where hostname.local resolves correctly using Avahi + nss-mdns:
-
Packages:
avahi-daemon(running)nss-mdnsinstalled
-
systemctl status avahi-daemon→active (running) -
/etc/nsswitch.confcontains one of:hosts: files mdns4_minimal [NOTFOUND=return] dnsor
hosts: files mdns_minimal [NOTFOUND=return] dnsor
hosts: files dns mdns4_minimal -
getent hosts hostname.localreturns the correct IP -
ping hostname.localandssh hostname.localwork from other LAN hosts -
No conflicting
.localusage in corporate DNS, or it has been accounted for.
Next Step
If you’re wiring this up in a distro, container base image, or a larger fleet, the next logical step is to standardize your Avahi + nss-mdns configuration and test across a few representative hosts. Once the hosts: line and packages are consistent, hostname.local should be a boring detail instead of a recurring support ticket.