
AVAHI on Buildroot: how do I include avahi-daemon, enable it at boot, and add my /etc/avahi/services files?
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:
- Go to:
Target packages ---> - Enable Avahi:
Networking applications --->
[*] avahi ---> - Inside the Avahi submenu, select at least:
[*] avahi-daemon(the mDNS/DNS-SD daemon)- Optionally:
[*] avahi-utilsif you wantavahi-browse,avahi-publish, etc.
- 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:
- Use Buildroot’s built‑in Avahi init script (if the package enables one).
- Provide your own init script via an overlay.
- Manage
avahi-daemonfrom 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. %his 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:
- In
make menuconfig:- Enable
avahi→avahi-daemon(and optionallyavahi-utils). - Enable
dbusif you later want D-Bus API access.
- Enable
- Configure a root filesystem overlay:
System configuration --->- Set
Root filesystem overlay directoriesto:board/<vendor>/<board>/rootfs-overlay
- Populate the overlay:
/etc/init.d/S50avahi(startavahi-daemon -Don boot)/etc/avahi/services/http.service/etc/avahi/services/ssh.service
- Rebuild and flash:
make- Deploy the generated image.
- On first boot:
- Confirm
ps | grep avahi-daemonshows a running daemon. - Use
avahi-browse -afrom another Linux or macOS host to verify your services are visible via Bonjour/Zeroconf.
- Confirm
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:
-
Enable
nss-mdns:Target packages --->Networking applications --->[*] nss-mdns
-
Adjust
/etc/nsswitch.confin your overlay so thehostsline includesmdnsormdns4: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/S50avahipermissions (chmod +x). - Confirm your overlay is referenced in
System configuration → Root filesystem overlay directories. - For systemd, verify
avahi-daemon.serviceis inmulti-user.target.wants.
- Check
-
Services not visible from other devices
- Confirm
/etc/avahi/services/*.serviceexist on the target (ls /etc/avahi/services). - Check Avahi logs; run
avahi-daemon -f -din foreground temporarily for verbose output. - Validate service XML against the DTD: correct
<type>,<port>, and no invalid characters.
- Confirm
-
*.local names don’t resolve
- Ensure
nss-mdnsis built into the image. - Confirm
nsswitch.confcontainsmdns/mdns4inhosts. - Verify that
avahi-daemonis running and advertising the host.
- Ensure
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.