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

Yocto makes it straightforward to ship Avahi as a first-class system service, but you need to pull in the right recipes and wire up both avahi-daemon and D-Bus so mDNS/DNS-SD actually runs on the target. Below is a practical, image-level recipe for getting from “no Avahi” to “Bonjour/Zeroconf-style discovery is running at boot” on a Yocto-based system.

Note: Commands and variables assume a reasonably recent Yocto release with systemd as PID 1. Adjust naming if you’re on older branches or using SysV init.


1. Know what you’re enabling: avahi-daemon + D-Bus

Avahi’s architecture on Yocto looks the same as on any other Linux:

  • avahi-daemon: the mDNS/DNS-SD daemon that does the actual multicast traffic on the LAN.
  • D-Bus (usually system bus): the primary API Avahi exposes for browsing and registering services.
  • Client tools (avahi-browse, avahi-publish, etc.): useful for debugging and simple registration.
  • Optional extras:
    • nss-mdns: allows *.local hostname resolution in “all system programs using nsswitch.”
    • Avahi libraries: for C clients or bindings in higher-level languages.

For most Yocto images, you want at least:

  • avahi-daemon
  • dbus + dbus-daemon
  • nss-mdns (if you expect hostname.local to resolve from generic programs and shells)

2. Add Avahi and D-Bus to your Yocto image

In Yocto, Avahi is supplied by the avahi recipe (in poky or your BSP layer), which in turn produces multiple binary packages. The exact split varies slightly by distro config, but the common pattern is:

  • avahi-daemon – the daemon and systemd unit
  • avahi-utilsavahi-browse, avahi-publish, etc.
  • avahi-autoipd – link-local IPv4 support (optional)
  • libavahi-* – client libraries (for your own applications)

You normally include packages at the image level.

2.1 Add packages to IMAGE_INSTALL

In your image recipe (e.g., core-image-minimal.bbappend, your-product-image.bb) add:

IMAGE_INSTALL:append = " avahi-daemon avahi-utils dbus"

If you want *.local hostnames via mDNS through nsswitch (highly recommended):

IMAGE_INSTALL:append = " avahi-daemon avahi-utils dbus nss-mdns"

That’s usually enough to pull in all the necessary libraries and dependencies. If your BSP splits D-Bus differently, you may need dbus-daemon instead of plain dbus, but most default setups pull the daemon when you add dbus.

2.2 Ensure you have the right layer and recipe

Verify the Avahi recipe is available:

bitbake-layers show-recipes | grep -i avahi

You should see something like:

avahi:
  avahi_0.8.bb ...

If you don’t see it:

  • Add meta-networking or another layer that ships avahi, depending on your Yocto version and vendor BSP.
  • Then rerun bitbake-layers show-recipes to confirm.

3. Enable D-Bus on the target image

Avahi’s primary API is D-Bus and “required for usage of most of Avahi.” On systemd-based Yocto images, D-Bus integration looks like this:

  1. Install D-Bus packages (already handled by IMAGE_INSTALL:append = " dbus").
  2. Ensure systemd services for D-Bus are enabled (this is typically automatic when systemd is your init system).
  3. For more explicit control, you can add D-Bus to DISTRO_FEATURES if your distro is extremely stripped down.

3.1 Check DISTRO_FEATURES

In conf/distro/<your-distro>.conf (or local.conf for local experimentation), confirm:

DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"

D-Bus doesn’t have to be in DISTRO_FEATURES itself; pulling in the dbus package is usually enough. But systemd-based images will then start the D-Bus service at boot.


4. Enable avahi-daemon as a systemd service

Yocto’s avahi recipe typically installs avahi-daemon.service and enables it via the standard systemd conventions once the package is installed. Still, it’s common to make the enablement explicit.

4.1 Use SYSTEMD_AUTO_ENABLE

If you’re writing a custom recipe for your own image or meta-layer, you can explicitly enable Avahi’s systemd unit in the recipe that depends on it:

SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE:${PN} += "avahi-daemon.service"

If you prefer to keep systemd configuration in the image recipe, you can also use IMAGE_INSTALL plus systemd’s preset mechanisms, but SYSTEMD_AUTO_ENABLE is the straightforward way when a package ships the unit.

4.2 Verify at runtime

On the target, check:

systemctl status avahi-daemon

You should see something like:

Loaded: loaded (/lib/systemd/system/avahi-daemon.service; enabled; ...)
Active: active (running)

If it’s not running:

systemctl enable avahi-daemon
systemctl start avahi-daemon

If these commands fail, double-check:

  • avahi-daemon.service exists under /lib/systemd/system or /etc/systemd/system.
  • The package avahi-daemon is actually present on the rootfs (use opkg list-installed | grep avahi or the appropriate package manager for your image).

5. Optional but recommended: nss-mdns for *.local resolution

The Avahi docs explicitly point to nss-mdns as the component that lets “hostname lookup of *.local hostnames via mDNS in all system programs using nsswitch.” On Yocto, treat this as a separate package:

5.1 Add nss-mdns to the image

IMAGE_INSTALL:append = " nss-mdns"

5.2 Configure /etc/nsswitch.conf

Ensure the hosts line includes mdns (or mdns4/mdns6) before or alongside dns. Example:

hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4

On some Yocto images, the nss-mdns package installs a sample nsswitch.conf fragment. If not, you may need to adjust it via:

  • A custom ROOTFS_POSTPROCESS_COMMAND, or
  • A small configuration recipe that installs a specific nsswitch.conf.

5.3 Test resolution

On the target:

ping hostname.local

If hostname.local corresponds to a machine advertising via Avahi/Bonjour on your LAN, it should resolve. If it doesn’t:

  • Confirm avahi-daemon is running on that host.
  • Check your nsswitch.conf ordering.
  • Use avahi-browse -a to see if services and hostnames appear at all.

6. Minimal Yocto configuration example

Here’s a small, concrete configuration set that takes a systemd-based Yocto image from “no Avahi” to “mDNS/DNS-SD enabled at boot”:

6.1 In conf/local.conf (or your distro config)

DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"

6.2 In your image recipe, e.g., my-avahi-image.bb

DESCRIPTION = "My Yocto image with Avahi/mDNS support"
LICENSE = "MIT"

inherit core-image

IMAGE_INSTALL:append = " \
    avahi-daemon \
    avahi-utils \
    dbus \
    nss-mdns \
"

If you want to be explicit about systemd service enablement inside an additional package recipe you own:

SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE:${PN} += "avahi-daemon.service"

Build the image:

bitbake my-avahi-image

Flash/run it, then on the target:

systemctl status dbus
systemctl status avahi-daemon
avahi-browse -a

You should see mDNS traffic and discovered services.


7. Using the Avahi APIs on Yocto

Once avahi-daemon and D-Bus are in place, your applications talk to Avahi exactly as they would on any other Linux box.

The Avahi docs describe three main APIs:

  • D-Bus API (recommended):
    “An extensive D-Bus interface for browsing and registering mDNS/DNS-SD services using avahi-daemon. We recommend using this API for software written in any language other than C (e.g. Python).”

  • C client libraries (libavahi-client, libavahi-common):
    For native C integration with the running daemon.

  • Embedded stack API (not recommended for normal desktops):
    Only for embedded appliances that need to embed the full mDNS stack; avoid running multiple stacks on a single host.

On Yocto, nothing changes here: the system bus is available, and /etc/avahi/services works the same way for static XML registrations.

7.1 Static service publication via /etc/avahi/services

If you want a service on your Yocto device to be advertised without a custom publisher:

  1. Install a service definition:

    <!-- /etc/avahi/services/my-http.service -->
    <service-group>
      <name replace-wildcards="yes">%h HTTP</name>
      <service>
        <type>_http._tcp</type>
        <port>80</port>
      </service>
    </service-group>
    
  2. Ensure avahi-daemon is running.

  3. From another machine, run avahi-browse -a or use a Bonjour client; you should see <hostname> HTTP on _http._tcp.

Yocto’s rootfs build will include this file if you add it via a recipe (e.g., SRC_URI with install in do_install()).


8. Common Yocto-specific pitfalls

A few recurring issues when integrating Avahi on Yocto-based systems:

  1. Avahi installed but not running

    • Cause: systemd is not configured as VIRTUAL-RUNTIME_init_manager, or avahi-daemon.service isn’t enabled.
    • Check: ps aux | grep avahi-daemon, systemctl status avahi-daemon.
  2. D-Bus not available

    • Cause: stripped-down image without dbus package, or wrong init system.
    • Symptom: clients using Avahi’s D-Bus API fail to connect to the system bus.
  3. hostname.local doesn’t resolve

    • Cause: nss-mdns missing or nsswitch.conf doesn’t include mdns.
    • Fix: IMAGE_INSTALL:append = " nss-mdns" and update hosts: line.
  4. Multiple mDNS stacks accidentally running

    • Cause: embedded application linking the Avahi “full mDNS/DNS-SD stack” directly while avahi-daemon also runs.
    • Fix: for standard Yocto systems, use the D-Bus API or C client library against avahi-daemon; avoid running a second mDNS stack.

Final decision framework

On a Yocto image, treat Avahi as a normal system component:

  • Add avahi-daemon, avahi-utils, and dbus to IMAGE_INSTALL to get the daemon and D-Bus.
  • Add nss-mdns if you want *.local resolution in all programs via nsswitch.
  • Use systemd as the init system and ensure avahi-daemon.service is enabled so mDNS/DNS-SD is running at boot.
  • Integrate your applications via D-Bus or /etc/avahi/services rather than embedding an extra mDNS stack.

Once these pieces are in place, your Yocto-based devices behave like any other Linux system with Avahi: they can “find printers to print to” and “find files being shared” on the LAN with Bonjour/Zeroconf-compatible discovery.

Next Step

Get Started