Publish a Local HTTP Service with systemd.dnssd

systemd.dnssd lets a machine announce an HTTP service over Multicast DNS, so other devices on the network can find it by name.

The guide uses systemd.dnssd(5) from systemd 255.4-1ubuntu8.17, installed on this machine. Give it 15 minutes, plus time to go and test from a second device on the same network. You need a running HTTP service, its listening port, a shell, and sudo to create a system configuration file. The service has to be reachable on the machine's network interface, and Multicast DNS has to be enabled on that interface already: this guide does not turn on mDNS or touch firewall rules for you.

1. Confirm the service you are about to publish

Nail down the real port before you write the DNS-SD file. The example below uses port 8080, advertising /status as a useful path on a local HTTP server:

ss -ltn | grep ':8080'

You want a listening TCP socket back, something like:

LISTEN 0      4096         0.0.0.0:8080      0.0.0.0:*

Nothing printed means stop here and fix or start the HTTP service first: a DNS-SD announcement never conjures a listener out of thin air. If the service only binds 127.0.0.1, no other machine can reach it even after mDNS finds it.

2. Write the service announcement

Create a file ending exactly in .dnssd under /etc/systemd/dnssd. The filename is the internal service file name, not what gets shown to users. This writes real system state, so read the heredoc carefully before running it with elevated privileges:

sudo install -d -m 0755 /etc/systemd/dnssd
sudo tee /etc/systemd/dnssd/site-http.dnssd >/dev/null <<'EOF'
[Service]
Name=%H
Type=_http._tcp
Port=8080
TxtText=path=/status role=internal
EOF

Name=%H expands to the machine's hostname. Type=_http._tcp identifies the service type, and Port=8080 has to match the listener you just checked. TxtText publishes whitespace-separated key/value pairs as human-readable TXT data, so only put values there you are happy for every device on the local network to see.

Checkpoint: read back exactly what landed on disk:

sudo sed -n '1,20p' /etc/systemd/dnssd/site-http.dnssd

You should see one [Service] section and the four assignments above. This file is not a systemd service unit, so do not try systemctl start site-http on it; it never was that kind of file.

3. Know which fields change what

4. Verify the announcement from a client

Query the service type with resolvectl:

resolvectl service _http._tcp.local

A working result names a hostname, an address, the advertised port and the TXT properties. The installed manpage shows an instance-specific query too:

resolvectl service my-host._http._tcp.local

Use whatever instance name discovery actually showed you, not the literal placeholder my-host. Run the query on the publishing host first, then from a second machine on the same network. An empty result on the second machine points at mDNS not being enabled on one of the interfaces, multicast traffic being blocked, or the HTTP listener not actually being reachable: all separate from the .dnssd file itself.

If Avahi is installed on the other host, the manpage's complementary check is:

avahi-browse -a -r

Look for the HTTP service with the expected port and TXT entries. Discovery working is evidence the announcement travelled, not proof the application behind it is healthy, so follow up with a normal HTTP request to the advertised path.

5. Change configuration without precedence surprises

systemd-resolved reads .dnssd files from /usr/lib/systemd/dnssd, /usr/local/lib/systemd/dnssd, /run/systemd/dnssd and /etc/systemd/dnssd. Files are read in lexical order, but a same-named file in a higher-priority directory replaces the lower one entirely. /etc wins over /run, which wins over the vendor locations.

For a small local tweak, use a drop-in directory such as /etc/systemd/dnssd/site-http.dnssd.d/. Only files ending in .conf are read there, and each one needs its own section header:

sudo install -d -m 0755 /etc/systemd/dnssd/site-http.dnssd.d
sudo tee /etc/systemd/dnssd/site-http.dnssd.d/10-metadata.conf >/dev/null <<'EOF'
[Service]
TxtText=path=/status role=internal owner=platform
EOF

A drop-in assignment does not remove an earlier TXT value automatically. To reset a prior TxtText or TxtData, assign it an empty string first, then add the replacements. Keep the main file and its drop-ins in source control, or at least recorded somewhere in your host configuration.

6. Recover or remove the announcement

To undo everything in this guide, remove the file and its optional drop-in directory. That stops the configuration being read on the next reload; it does not stop the HTTP server itself:

sudo rm -f /etc/systemd/dnssd/site-http.dnssd.d/10-metadata.conf
sudo rmdir /etc/systemd/dnssd/site-http.dnssd.d 2>/dev/null || true
sudo rm -f /etc/systemd/dnssd/site-http.dnssd

Recovery: the removal is irreversible unless you kept a copy, so save the file before deleting it if you might want the announcement back. Do not delete files under /usr/lib/systemd/dnssd to hide a vendor service; mask or override the local configuration instead.

After any change, repeat the resolvectl service query and check the result matches the port and TXT data you intended. If an old result lingers, allow for DNS-SD cache expiry before assuming the file is still active.

Done means