Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
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?

AVAHI8 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

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 | Codeables | Codeables