Skip to main content

max / alloy

mdns: resolve a .local name, not just publish one Alloy could announce <hostname>.local and could not look one up. avahi was enabled and publishing; nss-mdns was absent, so nsswitch went straight from myhostname to resolved, which ships MulticastDNS=no. A mismatch rather than a missing feature, and it surfaces on the machine doing the looking rather than the one that is broken. That matters more than tidiness now: a headless machine minted with a baked hostname is reached at <name>.local, so ssh installer@bench.local is the install flow, and it failed on the client side. nss-mdns needs no nsswitch edit. /etc/nsswitch.conf is a symlink into authselect and the package's own %post inserts mdns4_minimal [NOTFOUND=return] ahead of resolve, which is the ordering wanted; doing it by hand would fight authselect for a generated file. avahi is listed despite already being installed. It arrived as a weak dependency behind cups-libs and pipewire and enabled itself from its own preset, so a responder ran on every install that nobody chose. Naming it and its unit makes that a decision, and stops a future dependency change from silently removing something the install flow depends on. systemd-resolved is left alone: only one process can hold UDP 5353, so setting MulticastDNS=yes would break avahi rather than add anything. Verified in the base image: the hosts line, the resolver libraries, and the unit state. Not yet exercised against a real responder on a network.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-25 18:43 UTC
Signed with PGP, not checked
Commit: db989d984e0e255cd14d64cce6483292790d4b5e
Parent: 6ff9a45
2 files changed, +36 insertions, -0 deletions
@@ -288,6 +288,32 @@
288 288 tailscale \
289 289 syncthing \
290 290 restic \
291 + # Local discovery, both halves. Alloy could already ANNOUNCE a .local
292 + # name and could not RESOLVE one, which is a mismatch rather than a
293 + # missing feature, and it only shows up on the machine doing the
294 + # looking.
295 + #
296 + # avahi is listed here despite already being present. It arrived as a
297 + # weak dependency (avahi-libs comes in behind cups-libs, pipewire,
298 + # samba-client-libs, geoclue2) and enabled itself from its own package
299 + # preset, so the responder ran on every install without anyone choosing
300 + # it. Naming it makes that a decision, and keeps a future dependency
301 + # change from silently removing something the install flow now needs:
302 + # a headless box minted with a baked hostname is reached at
303 + # `<name>.local`, so publishing is load-bearing.
304 + #
305 + # nss-mdns is the half that was missing. It needs no nsswitch edit from
306 + # us: /etc/nsswitch.conf is a symlink into authselect, and the package's
307 + # own %post inserts `mdns4_minimal [NOTFOUND=return]` ahead of `resolve`,
308 + # which is the ordering wanted. Doing it by hand would fight authselect
309 + # for ownership of a generated file.
310 + #
311 + # systemd-resolved is left alone. It ships `MulticastDNS=no` compiled in,
312 + # so it is not competing for UDP 5353; setting it to `yes` would break
313 + # avahi rather than add anything, since only one process can hold that
314 + # port.
315 + avahi \
316 + nss-mdns \
291 317 # Greeter
292 318 greetd \
293 319 tuigreet \
@@ -57,6 +57,16 @@
57 57 # simply collects nothing.
58 58 enable rasdaemon.service
59 59
60 + # avahi, like sshd below, was already enabled by its own package preset and by
61 + # nobody's decision. Stated here because it is now load-bearing: a headless
62 + # machine minted with a baked hostname is found at `<name>.local`, so the
63 + # responder going away would break the install flow rather than merely remove a
64 + # convenience. The resolving half is nss-mdns, which needs no unit.
65 + #
66 + # The exposure is a multicast responder on every install, answering on the local
67 + # link only. Bounded by what mDNS is: TTL 1, no routing past the subnet.
68 + enable avahi-daemon.service
69 +
60 70 # sshd was already on before this line existed: openssh-server is in
61 71 # fedora-bootc:43 and Fedora enables it in 90-default.preset, which this file
62 72 # never overrode. So the state does not change here. What changes is that it