
How do I publish a custom service with AVAHI using an XML file in /etc/avahi/services (example for HTTP on port 8080)?
Most Linux fleets that ship Avahi by default use the XML route in /etc/avahi/services for simple, static services. If all you want is “advertise an HTTP endpoint on port 8080 so Bonjour/Zeroconf clients can see it,” you don’t need to touch the D-Bus API at all—an XML file and a daemon reload are enough.
Quick Answer: The best overall choice for publishing a custom HTTP service on port 8080 with Avahi is a static XML service file in
/etc/avahi/services. If your priority is dynamic control from applications, the D-Bus API is often a stronger fit. For DNS visibility of*.localhostnames to all system tools, consider pairing Avahi withnss-mdns.
At-a-Glance Comparison
| Rank | Option | Best For | Primary Strength | Watch Out For |
|---|---|---|---|---|
| 1 | Static XML in /etc/avahi/services | Simple, stable services (HTTP on port 8080, printers, file shares) | No code changes; Avahi handles mDNS/DNS-SD registration | Changes require editing files and reloading/restarting Avahi |
| 2 | D-Bus API (runtime registration) | Apps that must publish/unpublish dynamically | Full control over service lifetime and attributes | Requires coding against Avahi’s D-Bus/avahi-core API |
| 3 | nss-mdns + Avahi | Making hostname.local work in all CLI tools | Integrates mDNS with nsswitch for *.local lookups | Does not publish services by itself; only affects name resolution |
Comparison Criteria
We evaluated each option against the following criteria to keep the comparison practical and aligned with how Avahi is used in real systems:
- Setup complexity: How much configuration and code is required to publish or resolve the service.
- Operational control: How easily admins or applications can change, enable, or disable the service over time.
- Integration scope: Whether the approach covers just service advertisement, or also hostname resolution for
*.localacross all system programs viansswitch.
Detailed Breakdown
1. Static XML in /etc/avahi/services (Best overall for simple, stable services)
Static XML is the top choice because it uses Avahi’s built-in /etc/avahi/services mechanism, requires no application changes, and cleanly advertises HTTP on port 8080 via mDNS/DNS-SD.
What it does well:
-
No application code required:
Avahi’s primary API is D-Bus, but for straightforward publication you can drop an XML file in/etc/avahi/servicesand let the daemon handle everything. Your HTTP server just needs to listen on port 8080; Avahi will announce it on the LAN. -
Standards-compliant mDNS/DNS-SD records:
With the XML file, Avahi publishes the correct DNS-SD records so Bonjour/Zeroconf clients can browse and connect. This is ideal for “there’s a web UI on 8080” type services.A minimal example for HTTP on port 8080:
<!-- /etc/avahi/services/custom-http-8080.service --> <service-group> <name replace-wildcards="yes">%h HTTP on 8080</name> <service> <type>_http._tcp</type> <port>8080</port> <!-- Optional TXT records to describe the service --> <txt-record>path=/</txt-record> <txt-record>version=1</txt-record> </service> </service-group>Key fields:
<name replace-wildcards="yes">%h HTTP on 8080</name>
Uses the local hostname (%h) and lets Avahi adjust on collisions.<type>_http._tcp</type>
Standard DNS-SD type for HTTP services.<port>8080</port>
The TCP port where your HTTP server is listening.<txt-record>…</txt-record>
Optional extra metadata (path, version, etc.). Since Avahi 0.7, non-text/binary TXT data can also be encoded in XML definitions.
Operational steps to publish the service:
-
Ensure Avahi is installed and running
On most distributions Avahi ships by default, but confirm:
# Debian/Ubuntu sudo apt-get install avahi-daemon # Fedora/RHEL sudo dnf install avahi avahi-tools # Arch sudo pacman -S avahiEnable and start:
sudo systemctl enable avahi-daemon sudo systemctl start avahi-daemon -
Create the XML file in
/etc/avahi/servicessudo mkdir -p /etc/avahi/services sudo nano /etc/avahi/services/custom-http-8080.servicePaste the XML example above and save.
-
Reload or restart Avahi
Avahi picks up new service definitions on restart; some setups will also detect changes on reload.
sudo systemctl restart avahi-daemon -
Verify that the service is published
From another Linux host with Avahi tools:
avahi-browse -rt _http._tcpYou should see something like:
= eth0 IPv4 myhost HTTP on 8080 _http._tcp localFrom macOS (Bonjour), use
dns-sd:dns-sd -B _http._tcp
Tradeoffs & Limitations:
- Changes require config edits and reloads:
Any change (port, TXT records, service type) means editing the XML file in/etc/avahi/servicesand reloading/restartingavahi-daemon. This is fine for stable services but not ideal for rapidly changing configurations.
Decision Trigger: Choose XML in /etc/avahi/services if you want to publish HTTP on port 8080 (and similar services) in a predictable, distro-friendly way and prioritize minimal setup over application-level control.
2. D-Bus API (runtime registration) (Best for dynamic control from applications)
The D-Bus API is the strongest fit when your application needs to programmatically register, update, or withdraw services during its own lifecycle instead of relying on static config files.
What it does well:
-
Dynamic service lifecycle management:
Using Avahi’s primary API (D-Bus/avahi-core), your program can:- Create entry groups (
avahi_entry_group_new()). - Add services (
avahi_entry_group_add_service()). - Commit or reset groups as the application starts, changes ports, or shuts down.
This is useful when ports are assigned dynamically, or when you only want the service visible when a particular component is active.
- Create entry groups (
-
Richer integration with daemon state:
You can react to Avahi server states likeAVAHI_SERVER_COLLISIONandAVAHI_SERVER_REGISTERING. For example, if the local hostname changes due to a collision, you can move or re-register services at runtime so they remain reachable.
Tradeoffs & Limitations:
- Requires application changes and API usage:
Using the D-Bus API means writing code against Avahi’s client libraries or D-Bus interfaces. That’s appropriate for service daemons or desktop apps, but overkill if your only goal is a single HTTP service on port 8080.
Decision Trigger: Choose the D-Bus API if you want your application to own service registration directly, need to handle daemon restarts and hostname collisions programmatically, and prioritize fine-grained runtime control over simple static configuration.
3. nss-mdns + Avahi (Best for wide *.local hostname visibility)
nss-mdns stands out when the main problem isn’t publishing services, but making hostname.local work in every system tool (CLI, libraries, etc.) via nsswitch.
What it does well:
-
Integrates mDNS with
nsswitch:
Thenss-mdnsproject allows hostname lookup of*.localhostnames via mDNS in all system programs that usensswitch. This makes:ping myhost.local curl http://myhost.local:8080/ ssh user@myhost.localwork as expected without hard-coding IP addresses, as long as Avahi is running and the names are being advertised.
-
Complements Avahi service discovery:
Avahi handles mDNS/DNS-SD service publication and browsing.nss-mdnshandles name resolution integration with glibc via/etc/nsswitch.conf. Together, you get both “find HTTP services on 8080” and “resolvemyhost.localeverywhere.”
Tradeoffs & Limitations:
- Does not publish services itself:
nss-mdnsonly affects how hostnames are resolved; it doesn’t advertise your HTTP service on port 8080. You still need Avahi (via XML or D-Bus) to publish the_http._tcpservice.
Decision Trigger: Choose nss-mdns (alongside Avahi) if you want CLI tools and other system programs to resolve *.local names across the LAN and prioritize broad hostname resolution over just service browsing.
Final Verdict
For the specific question of how to publish a custom service with Avahi using an XML file in /etc/avahi/services—for example, an HTTP endpoint on port 8080—the cleanest approach is a static service definition in /etc/avahi/services/custom-http-8080.service, followed by an avahi-daemon restart and verification with avahi-browse or dns-sd.
If your needs grow more complex, use the D-Bus API for runtime-controlled registration or add nss-mdns so *.local hostnames work consistently across all nsswitch-aware tools. But for the common “announce an HTTP UI on port 8080” pattern, the XML-based method is the best overall fit.