
AVAHI on Yocto: which recipes/packages do I add, and how do I enable avahi-daemon and D-Bus in the image?
On Yocto-based systems, getting Avahi working is mostly about pulling in the right recipes, ensuring D-Bus is present, and wiring up the right services so that avahi-daemon comes up at boot. Below is a practical, image-level view I use when I’m integrating mDNS/DNS-SD into embedded distributions.
1. What you actually need in a Yocto image
Avahi is split into several packages. On Yocto, you rarely add the recipe name alone; you add the specific runtime packages (the RDEPENDS) to your image.
For a basic but fully functional mDNS/DNS-SD setup on an embedded target, you typically want:
avahi-daemon– the main mDNS/DNS-SD daemonavahi-autoipd(optional) – IPv4LL auto-addressing for link-local setupsavahi-utils(optional, but I strongly recommend for debugging) –avahi-browse,avahi-resolve-host-name, etc.avahi-dev/libavahi-*(only if you are compiling apps against the Avahi libraries on-target; often not in production images)
On top of that, Avahi requires D-Bus for most of its functionality:
dbus– the system D-Bus daemondbus-dev(only if you’re building software that talks to D-Bus at build time, e.g., via introspection)
And if you want hostname.local to work from standard tools (ping, ssh, etc.) via mDNS:
nss-mdns– addsmdns/mdns4resolution tonsswitch.confso all libc-based lookups can resolve*.local.
At the recipe layer, this all typically comes from:
meta-networking(for Avahi, sometimesmeta-oedepending on Yocto release / layer structure)meta-openembedded(fornss-mdns)
Make sure you have those layers added to bblayers.conf before you try to use the packages.
2. Adding Avahi and D-Bus to your Yocto image
In a custom image recipe (e.g., recipes-core/images/my-image.bb), declare Avahi and D-Bus as part of IMAGE_INSTALL.
Example minimal snippet:
IMAGE_INSTALL:append = " \
avahi-daemon \
avahi-autoipd \
avahi-utils \
dbus \
"
If you want mDNS-based *.local resolution to work system-wide:
IMAGE_INSTALL:append = " \
avahi-daemon \
avahi-autoipd \
avahi-utils \
dbus \
nss-mdns \
"
Notes:
- Use spaces and no line continuation backslashes inside the quoted string; Yocto concatenates these.
IMAGE_INSTALL:appendis usually cleaner than re-declaringIMAGE_INSTALLfrom scratch in an existing image.- Ensure you’ve added the
meta-networkingandmeta-openembeddedlayers that provide these recipes tobblayers.conf.
3. Enabling D-Bus: making sure the bus exists and starts
Avahi is built around D-Bus. The daemon expects a running system bus and will not be happy without it.
On a systemd-based image (the common case):
-
Include systemd as init
Inlocal.confor your distro configuration:DISTRO_FEATURES:append = " systemd" VIRTUAL-RUNTIME_init_manager = "systemd" -
Install D-Bus
Already covered above;dbusinIMAGE_INSTALLpulls the service in. -
Confirm the D-Bus system service
The Yoctodbusrecipe ships a systemd unitdbus.service/dbus.socket. When installed in a systemd image, it is typically enabled by default. If you need to ensure this, you can add in a distro or image configuration:SYSTEMD_AUTO_ENABLE:append:pn-dbus = " enable"In practice, this is usually unnecessary;
dbusis a core component and gets enabled automatically in most setups.
On non-systemd setups (e.g., sysvinit), you’ll have /etc/init.d/dbus and you must ensure your image’s init scripts bring it up before avahi-daemon. In embedded Yocto images, new work is generally systemd-only, so I’ll focus on that path.
4. Enabling avahi-daemon at boot on Yocto (systemd)
Once avahi-daemon is installed in an image that uses systemd, you need to ensure its unit is enabled so the daemon starts at boot.
The Avahi Yocto recipe normally provides a systemd unit like avahi-daemon.service. There are two main ways to ensure it’s enabled:
4.1 Using SYSTEMD_SERVICE and SYSTEMD_AUTO_ENABLE (recipe-centric)
If you are maintaining a custom Avahi recipe or bbappend, you can explicitly declare which services Avahi exposes and that they should be auto-enabled:
SYSTEMD_PACKAGES = "avahi-daemon"
SYSTEMD_SERVICE:avahi-daemon = "avahi-daemon.service"
SYSTEMD_AUTO_ENABLE:avahi-daemon = "enable"
That’s the pattern Yocto uses in recipes. Once baked, any image that installs avahi-daemon will have the service enabled by default.
4.2 Using SYSTEMD_AUTO_ENABLE from the image (image-centric)
If you don’t want to touch the Avahi recipe and just want your image to enable the service, you can append from the image side:
IMAGE_INSTALL:append = " avahi-daemon"
SYSTEMD_AUTO_ENABLE:append:pn-avahi-daemon = " enable"
Yocto’s systemd class will then generate the necessary systemctl enable calls at rootfs construction time, so when the image boots, avahi-daemon.service is already enabled.
4.3 Verifying at runtime
On a booted target:
systemctl status avahi-daemon
systemctl status dbus
You should see both active (or at least avahi-daemon waiting on D-Bus, then running). If they’re not active, check that:
- Your image really uses systemd (PID 1 is
systemd). avahi-daemon.serviceexists under/lib/systemd/system/or/etc/systemd/system/.- The unit is enabled (
systemctl is-enabled avahi-daemon).
5. Making hostname.local work: nss-mdns and nsswitch
Avahi alone gives you mDNS/DNS-SD. To make ping mydevice.local work in all programs that use libc name resolution, you need nss-mdns wired into nsswitch.
5.1 Install nss-mdns in the image
As shown earlier:
IMAGE_INSTALL:append = " nss-mdns"
nss-mdns is the companion module that allows hostname lookup of *.local via mDNS in all system programs using nsswitch.
5.2 Configure /etc/nsswitch.conf
Yocto typically installs nsswitch.conf from the base-files recipe (or a distro override). Make sure the hosts line includes mdns or mdns4.
Common patterns:
hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4
or a simpler variant:
hosts: files mdns4 dns
If your layer or distro does not patch this automatically, add a small bbappend to base-files or use a ROOTFS_POSTPROCESS_COMMAND in your image recipe to edit nsswitch.conf at rootfs creation time.
Example postprocess snippet:
ROOTFS_POSTPROCESS_COMMAND:append = " my_nsswitch_fix; "
my_nsswitch_fix () {
sed -i 's/^hosts:.*/hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4/' ${IMAGE_ROOTFS}/etc/nsswitch.conf
}
After boot, ping my-avahi-host.local should resolve via mDNS using the Avahi daemon.
6. Verifying Avahi on Yocto at runtime
Once the image is booted with Avahi and D-Bus installed and enabled:
-
Confirm the daemon sees the network and is running
systemctl status avahi-daemon journalctl -u avahi-daemon -
Browse the local mDNS space
From the target:
avahi-browse -aThis should show available services, including your own device advertising
_workstation._tcp, printers, SMB shares, etc., if present. -
Resolve a host via mDNS
Get another mDNS-speaking host on the same network (e.g., a macOS system with Bonjour) and test:
avahi-resolve-host-name other-host.localOr from the other side, resolve your Yocto device’s
.localhostname. -
Check D-Bus interface
If you’re using the D-Bus API directly, confirm you can see Avahi’s bus names and objects:
busctl --system list | grep Avahi # or dbus-send --system --print-reply \ --dest=org.freedesktop.Avahi \ /org/freedesktop/Avahi/Server \ org.freedesktop.Avahi.Server.GetVersionStringYou should get a reply with the Avahi version.
7. Typical Yocto pitfalls with Avahi
From shipping Avahi in multiple Yocto-based distros, these are the usual failure modes:
-
D-Bus not in the image
avahi-daemonis installed, butdbusis not, so the daemon fails to start or exits immediately. Fix: adddbustoIMAGE_INSTALL. -
SysV init vs systemd mismatch
The image still uses sysvinit while you’re expecting systemd units to be honored. ConfirmVIRTUAL-RUNTIME_init_managerandDISTRO_FEATURESin your distro config. -
nss-mdns installed but not wired into
nsswitch.conf
avahi-browseworks, butping host.localfails. Fix: patch thehosts:line innsswitch.confto includemdns/mdns4. -
Firewall rules blocking mDNS traffic
mDNS uses UDP/5353 on multicast 224.0.0.251 (IPv4) or ff02::fb (IPv6). Basic embedded images rarely ship restrictive firewalls, but if you do, allow incoming/outgoing multicast on that port. -
Multiple mDNS stacks
Running Avahi and another mDNS implementation (like some vendor-specific stack) on the same host can lead to undefined behavior. In embedded Yocto images, pick one mDNS stack; for Bonjour/Zeroconf compatibility on Linux, Avahi is the intended system component.
8. Minimal working example: one-image configuration
Putting it together, here’s a compact example of an image recipe fragment that:
- Uses systemd
- Installs Avahi, D-Bus, and nss-mdns
- Ensures Avahi is enabled at boot
- Adjusts
nsswitch.conffor*.localresolution
DESCRIPTION = "My Avahi-enabled image"
inherit core-image
DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
IMAGE_INSTALL:append = " \
avahi-daemon \
avahi-autoipd \
avahi-utils \
dbus \
nss-mdns \
"
# Make sure avahi-daemon is enabled
SYSTEMD_AUTO_ENABLE:append:pn-avahi-daemon = " enable"
# Adjust nsswitch.conf to use mdns
ROOTFS_POSTPROCESS_COMMAND:append = " my_nsswitch_fix; "
my_nsswitch_fix () {
sed -i 's/^hosts:.*/hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4/' ${IMAGE_ROOTFS}/etc/nsswitch.conf
}
Build this image, flash it, and you should have a target that:
- Runs
avahi-daemonon boot - Has a system bus (
dbus-daemon) running - Resolves
hostname.localvia mDNS across all standard tools
From there, you can layer on Avahi D-Bus integrations in your own applications, or publish static services using XML under /etc/avahi/services on the target, just as you would on a non-embedded Linux system.
If you run into edge cases—e.g., avahi-daemon failing after a D-Bus restart or odd behavior after a version bump—check the Avahi release notes (docs/NEWS) for any D-Bus/avahi-core API changes, and don’t hesitate to look at how your Yocto layer’s avahi recipe is patched relative to upstream.