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 Buildroot: how do I include avahi-daemon, enable it at boot, and add my /etc/avahi/services files?

AVAHI7 min read

Running Avahi on Buildroot is straightforward once you line it up with how Buildroot assembles the root filesystem and init scripts. You need to do three things: enable the Avahi packages in menuconfig, make sure the daemon is started at boot by your init system, and get your /etc/avahi/services/*.service XML files into the final image.

What follows is a distro‑maintainer style walkthrough you can drop into a Buildroot tree and reason about later when you debug “why isn’t my _http._tcp service visible from macOS Bonjour?”.


1. Enabling avahi-daemon in Buildroot

Avahi is split into multiple packages in Buildroot. At minimum, you want the daemon, and usually D-Bus as well if you’re using the primary Avahi API instead of only static XML services.

From the Buildroot tree:

make menuconfig

Then:

  1. Go to:
    Target packages --->
  2. Enable Avahi:
    Networking applications --->
    [*] avahi --->
  3. Inside the Avahi submenu, select at least:
    • [*] avahi-daemon (the mDNS/DNS-SD daemon)
    • Optionally: [*] avahi-utils if you want avahi-browse, avahi-publish, etc.
  4. If you’re using Avahi’s D-Bus API (recommended for most dynamic usage), also enable D-Bus:
    • Target packages --->
    • System tools --->
    • [*] dbus

Save and exit, then rebuild:

make

When the build completes, confirm Avahi is present in the target filesystem:

ls output/target/usr/sbin/avahi-daemon

If that binary exists, Buildroot has included it.


2. Making sure avahi-daemon starts at boot

Avahi is a system daemon. On Linux systems, AVAHI itself doesn’t manage startup; your init system does. Buildroot can use BusyBox init, systemd, or others depending on your configuration.

2.1. Check which init system your Buildroot config uses

In menuconfig:

make menuconfig

Look at:

  • System configuration --->
  • Init system (BusyBox / systemd / …)

The two common cases:

  • BusyBox init (Buildroot default on many configs)
  • systemd (if explicitly chosen)

Case A: BusyBox init (SysV‑style scripts)

With BusyBox init, the standard way is an /etc/init.d/Sxx… script.

You have three options:

  1. Use Buildroot’s built‑in Avahi init script (if the package enables one).
  2. Provide your own init script via an overlay.
  3. Manage avahi-daemon from a higher‑level script or supervisor (less common).

The robust approach is to ship your own predictable init script.

Step A1 – Create a simple init script

In your own source tree (outside Buildroot), create something like board/<vendor>/<board>/S50avahi:

#!/bin/sh

DAEMON=/usr/sbin/avahi-daemon
NAME=avahi-daemon
PIDFILE=/var/run/avahi-daemon.pid

case "$1" in
  start)
    echo "Starting $NAME"
    mkdir -p /var/run
    # Start with syslog logging and in the background
    $DAEMON -D
    ;;
  stop)
    echo "Stopping $NAME"
    if [ -f "$PIDFILE" ]; then
        kill "$(cat "$PIDFILE")" 2>/dev/null || true
        rm -f "$PIDFILE"
    else
        killall $NAME 2>/dev/null || true
    fi
    ;;
  restart)
    "$0" stop
    "$0" start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
esac

exit 0

Make it executable:

chmod +x board/<vendor>/<board>/S50avahi

Step A2 – Add it via a rootfs overlay

In menuconfig:

System configuration  --->
   (board/<vendor>/<board>/rootfs-overlay) Root filesystem overlay directories

Create that overlay directory and mirror the target path:

mkdir -p board/<vendor>/<board>/rootfs-overlay/etc/init.d
cp board/<vendor>/<board>/S50avahi \
   board/<vendor>/<board>/rootfs-overlay/etc/init.d/

Rebuild:

make

On boot, BusyBox init will run /etc/init.d/S50avahi start, bringing up avahi-daemon early in the boot sequence.

Case B: systemd

If your Buildroot configuration uses systemd, you should use a native service unit instead of SysV scripts.

Step B1 – Create a systemd unit file

In your overlay:

mkdir -p board/<vendor>/<board>/rootfs-overlay/etc/systemd/system

Create avahi-daemon.service:

[Unit]
Description=Avahi mDNS/DNS-SD Stack
After=network.target dbus.service
Requires=dbus.service

[Service]
Type=dbus
BusName=org.freedesktop.Avahi
ExecStart=/usr/sbin/avahi-daemon -s
Restart=on-failure

[Install]
WantedBy=multi-user.target

Step B2 – Enable the service

With systemd images, you typically symlink into multi-user.target.wants. In the overlay:

mkdir -p board/<vendor>/<board>/rootfs-overlay/etc/systemd/system/multi-user.target.wants
ln -sf ../avahi-daemon.service \
   board/<vendor>/<board>/rootfs-overlay/etc/systemd/system/multi-user.target.wants/avahi-daemon.service

Rebuild and boot. On first login, check:

systemctl status avahi-daemon

You should see the service active and the DBus name claimed.


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

Avahi’s XML service definitions are how you publish static services without writing a D-Bus publisher. That’s the first integration surface many embedded builds use.

Avahi will automatically load any *.service files from /etc/avahi/services when the daemon starts and whenever the directory changes.

You just need those XML files in the final root filesystem.

3.1. Create the XML service definitions

Example: publish an HTTP service on port 80:

board/<vendor>/<board>/rootfs-overlay/etc/avahi/services/http.service:

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

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

A few notes:

  • The <!DOCTYPE …> line should match Avahi’s expected DTD.
  • %h is replaced by the local hostname at runtime.
  • You can add TXT records as additional <txt-record> entries.

If you want multiple services (e.g., _ssh._tcp, _smb._tcp), add more *.service files in the same directory.

3.2. Wire the directory into the overlay

Make sure your overlay mirrors the target layout:

mkdir -p board/<vendor>/<board>/rootfs-overlay/etc/avahi/services
cp path/to/your/*.service \
   board/<vendor>/<board>/rootfs-overlay/etc/avahi/services/

The same Root filesystem overlay directories setting used for init scripts will also bring these XML files into /etc/avahi/services in the image.

3.3. Rebuild and verify in the output tree

After make, check the built rootfs:

ls output/target/etc/avahi/services
cat output/target/etc/avahi/services/http.service

If the files are present there, they’ll be present in your final image.

On a running device, verify that Avahi has loaded them:

avahi-browse -a
# or from another host on the same LAN
avahi-browse -a -r

You should see your %h HTTP service advertised as _http._tcp.


4. Example: end-to-end configuration summary

Putting it all together, for a BusyBox‑init Buildroot target that should publish HTTP and SSH via Avahi mDNS/DNS-SD:

  1. In make menuconfig:
    • Enable avahiavahi-daemon (and optionally avahi-utils).
    • Enable dbus if you later want D-Bus API access.
  2. Configure a root filesystem overlay:
    • System configuration --->
    • Set Root filesystem overlay directories to:
      • board/<vendor>/<board>/rootfs-overlay
  3. Populate the overlay:
    • /etc/init.d/S50avahi (start avahi-daemon -D on boot)
    • /etc/avahi/services/http.service
    • /etc/avahi/services/ssh.service
  4. Rebuild and flash:
    • make
    • Deploy the generated image.
  5. On first boot:
    • Confirm ps | grep avahi-daemon shows a running daemon.
    • Use avahi-browse -a from another Linux or macOS host to verify your services are visible via Bonjour/Zeroconf.

At that point, you have mDNS/DNS-SD running on a Buildroot‑based system, with Avahi reading static XML from /etc/avahi/services and starting automatically at boot.


5. Optional: *.local name resolution with nss-mdns

If you want hostname.local resolution to work in all system programs on your Buildroot target (not just via Avahi tools), you also need nss-mdns, which plugs into nsswitch.

In Buildroot:

  1. Enable nss-mdns:

    • Target packages --->
    • Networking applications --->
    • [*] nss-mdns
  2. Adjust /etc/nsswitch.conf in your overlay so the hosts line includes mdns or mdns4:

    echo 'hosts: files mdns4 dns' \
      > board/<vendor>/<board>/rootfs-overlay/etc/nsswitch.conf
    

Rebuild. Now standard tools like ping hostname.local or ssh hostname.local will use mDNS to resolve peer devices on the LAN, making your Buildroot system behave like other Bonjour/Zeroconf hosts.


6. Troubleshooting checklist

If your Avahi setup on Buildroot isn’t behaving:

  • Daemon not running at boot

    • Check /etc/init.d/S50avahi permissions (chmod +x).
    • Confirm your overlay is referenced in System configuration → Root filesystem overlay directories.
    • For systemd, verify avahi-daemon.service is in multi-user.target.wants.
  • Services not visible from other devices

    • Confirm /etc/avahi/services/*.service exist on the target (ls /etc/avahi/services).
    • Check Avahi logs; run avahi-daemon -f -d in foreground temporarily for verbose output.
    • Validate service XML against the DTD: correct <type>, <port>, and no invalid characters.
  • *.local names don’t resolve

    • Ensure nss-mdns is built into the image.
    • Confirm nsswitch.conf contains mdns/mdns4 in hosts.
    • Verify that avahi-daemon is running and advertising the host.

Once those pieces are in place, Avahi on Buildroot becomes a boring system component: your devices join the LAN, announce services from /etc/avahi/services, and participate cleanly in a Bonjour/Zeroconf environment without any extra infrastructure.

Get Started

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