Documentation

Last updated: 2026-07-27

Private networks: mDNS discovery

On a home or office LAN there is usually no DNS server you control and no public domain — but the image backend is still host-routed, so clients need a hostname that resolves to the box. Everlock solves this with mDNS: any image instance whose vhost ends in .local is announced on the local link, so every device on the network can reach it by name with zero DNS configuration. The same instances are also advertised over SSDP/UPnP, so they show up as clickable entries in Windows "Network".

This is the counterpart to public DNS + ACME hosting: same vhost mechanism, opposite environment.

When to use this

Reach for mDNS instead of public DNS when:

  • you are behind NAT on a typical home line (Fritz!Box and similar) and don't want to expose anything to the internet;
  • there is no DNS server on the LAN, or you don't want to edit /etc/hosts on every device;
  • you want the gallery to "just appear" on phones and laptops on the same network;
  • you are running several galleries and want each reachable by its own name across the LAN.

How it works

The mDNS frontend (frontend-mdns) is a separate, announcement-only transport. It does not serve traffic itself — it publishes records that point clients at the HTTP frontend.

flowchart LR
IMG["image instance (vhost: photos.local)"] -->|publishes .local vhost| REG["vhost registry"]
REG --> MDNS["frontend-mdns"]
MDNS -->|http / https service| LAN[("local link")]
MDNS -->|SSDP / UPnP device| LAN
Phone["phone / laptop / TV"] -->|resolves photos.local| LAN
Phone -->|request to photos.local| HTTP["frontend-http"]
HTTP --> IMG
mDNS turns .local vhosts into LAN-resolvable names that point back at the HTTP frontend.

On startup the mDNS frontend:

  1. collects every vhost ending in .local from the running backends (image instances included);
  2. detects a suitable local IPv4 address (skipping loopback and link-local), or uses the one named by --frontend-mdns-interface;
  3. announces each .local host as an _http._tcp or _https._tcp service — _https._tcp only when the HTTP frontend has HTTPS enabled, which for a purely local setup it usually does not;
  4. additionally advertises each .local vhost over SSDP/UPnP as a UPnP Basic device, so it appears as a clickable entry in Windows "Network" that opens the gallery in the browser.

The instance label is derived from the hostname by stripping .local — so photos.local is announced as the photos service on the link.

Enabling it

Turn on the mDNS frontend and give your image instance a .local vhost. The backend flags shown here bootstrap a single default instance; for several galleries use config/image-http.toml.

./everlock serve \
  --frontend-mdns \
  --backend-image-http \
  --backend-image-http-vhost photos.local \
  --backend-image-http-store family-images \
  --admin-user admin --admin-password change-me

Once running, any device on the LAN can open:

http://photos.local:8080/

Multiple galleries, multiple names

This is where mDNS shines for a household. Give each instance its own .local vhost and every one becomes independently discoverable — no DNS server, no certificates, no /etc/hosts edits on any device:

enabled = true

[instances.family]
store = "family-images"
vhosts = ["photos.local"]

[instances.kids]
store = "kids-images"
vhosts = ["kids.local"]

[instances.archive]
store = "archive-images"
vhosts = ["archive.local"]

After a restart, photos.local, kids.local, and archive.local all resolve across the LAN and each appears as its own entry in Windows "Network". Access is still scoped per instance via http/image/<instance> grants, so a .local name being visible does not mean it is open — a user still needs at least Reader to log in.

.local vhosts are always plain HTTP

A .local name can never hold a publicly-trusted TLS certificate, so Everlock never tries to issue one for it. localhost, *.local, and raw IPs are explicitly skipped by ACME and served over plain HTTP even when an HTTPS listener is configured. This is exactly what you want on a trusted LAN: no certificate warnings, no setup.

If an instance carries both a .local vhost and a public one, the public name is ACME-managed while the .local name stays plain HTTP — the frontend decides per-host. In that mixed case, remember that public_url derives from the first vhost, so list the routable public name first if you want share links to use it.

Tuning the announcement

The mDNS frontend exposes a few knobs:

Flag / envDefaultPurpose
--frontend-mdns / EVERLOCK_FRONTEND_MDNSoffenable the frontend
--frontend-mdns-interface / …_INTERFACEall suitablerestrict announcements to one interface
--frontend-mdns-ttl / …_TTL75record TTL in seconds
--frontend-mdns-instance / …_INSTANCEeverlocklabel for non-HTTP service records (e.g. SSH)
--frontend-mdns-ipv6 / …_IPV6offreserved — IPv6 announcements are not yet implemented and the flag is currently ignored with a warning

If no .local vhosts are configured, the frontend logs a warning and announces nothing — there is simply nothing for it to publish.

SSDP / UPnP specifics

Each .local vhost is exposed as a UPnP Basic device. That is what makes a gallery appear under Windows "Network" without typing a URL. The device's presentation URL points at http://<vhost>:<port> so the client sends the correct Host header and the request routes to the right instance. SSDP advertisement is limited to .local vhosts; public hostnames are not announced this way.

images mdns ssdp local home-network