AVAHI on Yocto: which recipes/packages do I add, and how do I enable avahi-daemon and D-Bus in the image?
Networking System Software

AVAHI on Yocto: which recipes/packages do I add, and how do I enable avahi-daemon and D-Bus in the image?

8 min read

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 daemon
  • avahi-autoipd (optional) – IPv4LL auto-addressing for link-local setups
  • avahi-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 daemon
  • dbus-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 – adds mdns/mdns4 resolution to nsswitch.conf so all libc-based lookups can resolve *.local.

At the recipe layer, this all typically comes from:

  • meta-networking (for Avahi, sometimes meta-oe depending on Yocto release / layer structure)
  • meta-openembedded (for nss-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:append is usually cleaner than re-declaring IMAGE_INSTALL from scratch in an existing image.
  • Ensure you’ve added the meta-networking and meta-openembedded layers that provide these recipes to bblayers.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):

  1. Include systemd as init
    In local.conf or your distro configuration:

    DISTRO_FEATURES:append = " systemd"
    VIRTUAL-RUNTIME_init_manager = "systemd"
    
  2. Install D-Bus
    Already covered above; dbus in IMAGE_INSTALL pulls the service in.

  3. Confirm the D-Bus system service
    The Yocto dbus recipe ships a systemd unit dbus.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; dbus is 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.service exists 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:

  1. Confirm the daemon sees the network and is running

    systemctl status avahi-daemon
    journalctl -u avahi-daemon
    
  2. Browse the local mDNS space

    From the target:

    avahi-browse -a
    

    This should show available services, including your own device advertising _workstation._tcp, printers, SMB shares, etc., if present.

  3. 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.local
    

    Or from the other side, resolve your Yocto device’s .local hostname.

  4. 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.GetVersionString
    

    You 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-daemon is installed, but dbus is not, so the daemon fails to start or exits immediately. Fix: add dbus to IMAGE_INSTALL.

  • SysV init vs systemd mismatch
    The image still uses sysvinit while you’re expecting systemd units to be honored. Confirm VIRTUAL-RUNTIME_init_manager and DISTRO_FEATURES in your distro config.

  • nss-mdns installed but not wired into nsswitch.conf
    avahi-browse works, but ping host.local fails. Fix: patch the hosts: line in nsswitch.conf to include mdns/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.conf for *.local resolution
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-daemon on boot
  • Has a system bus (dbus-daemon) running
  • Resolves hostname.local via 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.

Next Step

Get Started