
AVAHI on Buildroot: how do I include avahi-daemon, enable it at boot, and add my /etc/avahi/services files?
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-daemonin Buildroot - Ensure it starts automatically at boot
- Package your
/etc/avahi/services/*.servicefiles 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.serviceunit - 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/messagesordmesgfor 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.
- Create an overlay directory in your Buildroot tree, for example:
mkdir -p board/myboard/rootfs-overlay/etc/avahi/services
- Add your
.servicefiles:
cp web.service board/myboard/rootfs-overlay/etc/avahi/services/
- Configure Buildroot to use this overlay:
In menuconfig:
System configuration --->
(board/myboard/rootfs-overlay) Root filesystem overlay directories
- 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:
-
Enable Avahi and dependencies
Target packages → Networking applications → avahi- Enable
avahi-daemonand D-Bus support - Optionally enable
avahi-utils - Enable
dbusunder system tools if you use the D-Bus API
-
Ensure service startup
- For BusyBox init:
- Confirm
Sxxavahi-daemonexists in/etc/init.d - If not, add an init script via rootfs overlay
- Confirm
- For systemd:
- Use
avahi-daemon.service - Enable it via
systemctl enable avahi-daemonor a post-build hook
- Use
- For BusyBox init:
-
Add
/etc/avahi/servicesXML files- Create a rootfs overlay with
etc/avahi/services/*.service - Or add a custom Buildroot package that installs them into the target
- Create a rootfs overlay with
-
Optional:
*.localhostname resolution- Enable
nss-mdns - Adjust
/etc/nsswitch.confto includemdns/mdns4
- Enable
-
Rebuild and test
make- Boot the image
- Confirm
avahi-daemonis running - Use
avahi-browseordns-sdfrom 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.