How do I publish a custom service with AVAHI using an XML file in /etc/avahi/services (example for HTTP on port 8080)?
Networking System Software

How do I publish a custom service with AVAHI using an XML file in /etc/avahi/services (example for HTTP on port 8080)?

7 min read

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 *.local hostnames to all system tools, consider pairing Avahi with nss-mdns.

At-a-Glance Comparison

RankOptionBest ForPrimary StrengthWatch Out For
1Static XML in /etc/avahi/servicesSimple, stable services (HTTP on port 8080, printers, file shares)No code changes; Avahi handles mDNS/DNS-SD registrationChanges require editing files and reloading/restarting Avahi
2D-Bus API (runtime registration)Apps that must publish/unpublish dynamicallyFull control over service lifetime and attributesRequires coding against Avahi’s D-Bus/avahi-core API
3nss-mdns + AvahiMaking hostname.local work in all CLI toolsIntegrates mDNS with nsswitch for *.local lookupsDoes 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 *.local across all system programs via nsswitch.

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/services and 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:

  1. 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 avahi
    

    Enable and start:

    sudo systemctl enable avahi-daemon
    sudo systemctl start avahi-daemon
    
  2. Create the XML file in /etc/avahi/services

    sudo mkdir -p /etc/avahi/services
    sudo nano /etc/avahi/services/custom-http-8080.service
    

    Paste the XML example above and save.

  3. 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
    
  4. Verify that the service is published

    From another Linux host with Avahi tools:

    avahi-browse -rt _http._tcp
    

    You should see something like:

    = eth0 IPv4 myhost HTTP on 8080  _http._tcp  local
    

    From 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/services and reloading/restarting avahi-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.

  • Richer integration with daemon state:
    You can react to Avahi server states like AVAHI_SERVER_COLLISION and AVAHI_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:
    The nss-mdns project allows hostname lookup of *.local hostnames via mDNS in all system programs that use nsswitch. This makes:

    ping myhost.local
    curl http://myhost.local:8080/
    ssh user@myhost.local
    

    work 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-mdns handles name resolution integration with glibc via /etc/nsswitch.conf. Together, you get both “find HTTP services on 8080” and “resolve myhost.local everywhere.”

Tradeoffs & Limitations:

  • Does not publish services itself:
    nss-mdns only 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._tcp service.

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.

Next Step

Get Started