AVAHI on Buildroot: how do I include avahi-daemon, enable it at boot, and add my /etc/avahi/services files?
Networking System Software

AVAHI on Buildroot: how do I include avahi-daemon, enable it at boot, and add my /etc/avahi/services files?

7 min read

On Buildroot-based systems, Avahi works the same way it does on a mainstream distribution: the daemon provides mDNS/DNS-SD, and you publish static services by dropping XML files into /etc/avahi/services. The main differences are how you bring the daemon into the root filesystem, how it starts at boot, and where those XML files come from in your Buildroot configuration.

This guide walks through a minimal, reproducible setup:

  • Enable avahi-daemon in Buildroot
  • Ensure it starts automatically at boot
  • Package your /etc/avahi/services/*.service files into the image

All of this assumes a Linux-first environment (no Windows) and a standard Buildroot workflow with menuconfig and possibly custom packages or rootfs overlays.


1. Including avahi-daemon in a Buildroot image

Avahi is split into libraries and the daemon. For typical LAN discovery (e.g., “find printers to print to,” “find files being shared”), you want the daemon plus its tools.

1.1 Enable Avahi in menuconfig

From your Buildroot tree:

make menuconfig

Then navigate something like:

Target packages  --->
  Networking applications  --->
    [*] avahi    (or Avahi mDNS/DNS-SD)

Inside the Avahi submenu, select the daemon and tools:

  • [ * ] avahi-daemon
  • [ * ] avahi-utils (optional but useful: avahi-browse, avahi-resolve, etc.)
  • Disable features you don’t need (e.g., GTK/Qt GUIs) to keep the image small.

Save and exit. After this, avahi-daemon binaries and supporting files will be built into your target rootfs.

1.2 Dependencies and common options

Avahi’s primary API is D-Bus, and most of Avahi expects a D-Bus system bus to exist. In Buildroot this usually means:

Target packages  --->
  System tools  --->
    [*] dbus

In Avahi’s config menu, make sure you keep:

  • D-Bus support enabled if you plan to use the D-Bus API for dynamic registration/browsing.
  • IPv4 / IPv6 support according to your network stack. Most systems keep both.

When you rebuild:

make

you should see avahi-daemon and avahi-browse under output/target/usr/sbin or similar, depending on your Buildroot version.


2. Enabling avahi-daemon at boot

On Buildroot, service startup is usually handled by BusyBox init scripts (/etc/init.d/Sxx...) unless you’ve opted into systemd or another init system. The exact method depends on which init system you selected.

2.1 BusyBox init (Buildroot default)

Most Buildroot configs use BusyBox init with SysV-style scripts. In this setup, Avahi is expected to install an init script like /etc/init.d/S50avahi-daemon.

Confirm inside the target rootfs:

ls output/target/etc/init.d

Look for something like S50avahi-daemon, S51avahi-daemon, or avahi-daemon. If it exists, init will run it automatically at boot as long as it starts with S and is executable.

If the script is missing or named differently, you can add a minimal one via a rootfs overlay (see section 3.2). For BusyBox, a simple script is enough:

#!/bin/sh

DAEMON=/usr/sbin/avahi-daemon

case "$1" in
  start)
    echo "Starting avahi-daemon"
    start-stop-daemon -S -x "$DAEMON" -- -D
    ;;
  stop)
    echo "Stopping avahi-daemon"
    start-stop-daemon -K -x "$DAEMON"
    ;;
  restart)
    "$0" stop
    "$0" start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
esac

Place this as etc/init.d/S50avahi-daemon in your overlay (see below), make it executable, and rebuild.

2.2 systemd (if you use it in Buildroot)

If your Buildroot configuration uses systemd:

  • Enable systemd in menuconfig
  • Avahi will typically install a avahi-daemon.service unit
  • At runtime:
systemctl enable avahi-daemon
systemctl start avahi-daemon

You can pre-enable the unit via rootfs tweaks or custom Buildroot hooks, but many embedded flows just run systemctl enable in a post-build script.

2.3 Verifying the daemon at boot

After building and booting your image:

ps | grep avahi

You should see something like:

avahi     123   1  ... /usr/sbin/avahi-daemon -D
avahi     124 123 ... /usr/sbin/avahi-daemon: chroot helper

If not:

  • Check /var/log/messages or dmesg for Avahi startup errors
  • Verify D-Bus is running if you enabled D-Bus support
  • Confirm the init script or systemd unit is actually present and executable

3. Adding /etc/avahi/services files in Buildroot

Avahi supports XML service definitions in /etc/avahi/services so you can publish services without writing a custom D-Bus client. This is the most straightforward way to make a Buildroot-rooted system advertise fixed services.

3.1 How Avahi consumes /etc/avahi/services

At runtime:

  • Avahi scans /etc/avahi/services/*.service
  • Each file is an XML document describing a DNS-SD service (e.g. _http._tcp, _ipp._tcp)
  • When Avahi starts (or when files change), it publishes those services via mDNS/DNS-SD

Example: A minimal HTTP service definition:

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">

<service-group>
  <name replace-wildcards="yes">%h Web Interface</name>
  <service>
    <type>_http._tcp</type>
    <port>80</port>
  </service>
</service-group>

Save this as /etc/avahi/services/web.service on the target, and any Bonjour/Zeroconf-aware client should see it.

3.2 Using a rootfs overlay to add service files

The simplest Buildroot-compatible way to ship static XML files is a root filesystem overlay.

  1. Create an overlay directory in your Buildroot tree, for example:
mkdir -p board/myboard/rootfs-overlay/etc/avahi/services
  1. Add your .service files:
cp web.service board/myboard/rootfs-overlay/etc/avahi/services/
  1. Configure Buildroot to use this overlay:

In menuconfig:

System configuration  --->
  (board/myboard/rootfs-overlay) Root filesystem overlay directories
  1. Rebuild:
make

After the build, check:

ls output/target/etc/avahi/services

You should see your XML files. On boot, avahi-daemon will read these and publish the corresponding services.

3.3 Packaging services via a custom Buildroot package (alternative)

If you already maintain custom Buildroot packages, you can create a “config-only” package that installs service files.

Example skeleton (package/avahi-services/avahi-services.mk):

AVAHI_SERVICES_VERSION = 1.0
AVAHI_SERVICES_SITE = $(TOPDIR)/package/avahi-services/files
AVAHI_SERVICES_SITE_METHOD = local
AVAHI_SERVICES_INSTALL_TARGET = YES

define AVAHI_SERVICES_INSTALL_TARGET_CMDS
	$(INSTALL) -D -m 0644 $(@D)/web.service \
		$(TARGET_DIR)/etc/avahi/services/web.service
endef

$(eval $(generic-package))

And package/avahi-services/Config.in:

config BR2_PACKAGE_AVAHI_SERVICES
	bool "avahi-services"
	depends on BR2_PACKAGE_AVAHI
	help
	  Install static Avahi service XML definitions in /etc/avahi/services

Add the package to package/Config.in, enable it via menuconfig, and put web.service under package/avahi-services/files/.

This approach is useful when you need versioned, reproducible sets of service definitions tied to your Buildroot configuration.


4. Verifying Avahi service publication on the network

Once avahi-daemon is in the image, starts at boot, and sees your /etc/avahi/services files, you should validate from a second machine on the same LAN.

4.1 Using Avahi tools on another Linux machine

On a second Linux host with Avahi installed:

avahi-browse -a

You should see entries matching your <type> fields and hostnames, for example:

+   eth0 IPv4 myboard Web Interface  _http._tcp        local

To look up a specific type:

avahi-browse _http._tcp -rt

4.2 Using Bonjour/Zeroconf on macOS

On macOS, Avahi services appear just like native Bonjour:

dns-sd -B _http._tcp local

You should see your Buildroot-hosted device listed. That’s a practical confirmation that your mDNS/DNS-SD stack is interoperating correctly across platforms.


5. Optional: making hostname.local work with nss-mdns

If you want hostname.local resolution to work in all system programs via nsswitch, add nss-mdns in Buildroot and configure /etc/nsswitch.conf.

5.1 Enable nss-mdns in Buildroot

In menuconfig:

Target packages  --->
  Networking applications  --->
    [*] nss-mdns

Rebuild. The library should be installed into the target (e.g., /lib/libnss_mdns*.so).

5.2 Configure nsswitch for mDNS

In your rootfs overlay, add or modify /etc/nsswitch.conf:

hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4

Rebuild. After boot, a simple:

ping hostname.local

from a peer system should resolve via mDNS, assuming Avahi is running and publishing the host.


6. Putting it all together: a minimal Buildroot recipe

To summarize a clean end-to-end setup:

  1. Enable Avahi and dependencies

    • Target packages → Networking applications → avahi
    • Enable avahi-daemon and D-Bus support
    • Optionally enable avahi-utils
    • Enable dbus under system tools if you use the D-Bus API
  2. Ensure service startup

    • For BusyBox init:
      • Confirm Sxxavahi-daemon exists in /etc/init.d
      • If not, add an init script via rootfs overlay
    • For systemd:
      • Use avahi-daemon.service
      • Enable it via systemctl enable avahi-daemon or a post-build hook
  3. Add /etc/avahi/services XML files

    • Create a rootfs overlay with etc/avahi/services/*.service
    • Or add a custom Buildroot package that installs them into the target
  4. Optional: *.local hostname resolution

    • Enable nss-mdns
    • Adjust /etc/nsswitch.conf to include mdns/mdns4
  5. Rebuild and test

    • make
    • Boot the image
    • Confirm avahi-daemon is running
    • Use avahi-browse or dns-sd from another machine to see published services

With that in place, your Buildroot-based system will join the LAN, advertise services defined in /etc/avahi/services, and interoperate cleanly with Bonjour/Zeroconf tools and devices.

Next Step

Get Started