feat(mdns): optional Avahi .local responder (ENABLE_MDNS)
Self-contained host-network Avahi container publishes the service names over mDNS so .local works zero-config for guests (macOS/Linux native, Windows needs Bonjour). Toggle with ENABLE_MDNS=true + BASE_DOMAIN=*.local; build-stack layers docker-compose.avahi.yml in and builds the image during --prep. mDNS can't serve the air-gap upstream spoofs (non-.local) — those still need real DNS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
docker-compose.avahi.yml
Normal file
14
docker-compose.avahi.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# mDNS toggle — publish *.local service names over Avahi for zero-config guest
|
||||||
|
# resolution. Enabled when ENABLE_MDNS=true in .env (build-stack layers it in)
|
||||||
|
# and only meaningful when BASE_DOMAIN=*.local. Host networking is required for
|
||||||
|
# link-local multicast.
|
||||||
|
services:
|
||||||
|
avahi:
|
||||||
|
build: ./docker/avahi
|
||||||
|
image: ulicraft-avahi:local
|
||||||
|
container_name: avahi
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
BASE_DOMAIN: ${BASE_DOMAIN}
|
||||||
|
HOST_LAN_IP: ${HOST_LAN_IP}
|
||||||
8
docker/avahi/Dockerfile
Normal file
8
docker/avahi/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Self-contained mDNS responder: publishes the stack's service names on .local
|
||||||
|
# so guests resolve them with zero DNS/client config (macOS/Linux native;
|
||||||
|
# Windows needs Bonjour). Used only when ENABLE_MDNS=true and BASE_DOMAIN=*.local.
|
||||||
|
FROM alpine:3.20
|
||||||
|
RUN apk add --no-cache avahi dbus
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
32
docker/avahi/entrypoint.sh
Executable file
32
docker/avahi/entrypoint.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Publish A records for the stack's service names over mDNS (.local).
|
||||||
|
# Requires host networking (mDNS is link-local multicast). One avahi-publish
|
||||||
|
# per name; if any dies the container exits so Docker restarts it.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
: "${BASE_DOMAIN:?BASE_DOMAIN unset}"
|
||||||
|
: "${HOST_LAN_IP:?HOST_LAN_IP unset}"
|
||||||
|
|
||||||
|
case "$BASE_DOMAIN" in
|
||||||
|
*.local) ;;
|
||||||
|
*) echo "WARN: mDNS resolves only .local — BASE_DOMAIN=$BASE_DOMAIN will NOT be discoverable via avahi. Set BASE_DOMAIN=*.local to use mDNS." >&2 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mkdir -p /run/dbus
|
||||||
|
rm -f /run/dbus/pid /run/dbus/system_bus_socket 2>/dev/null || true
|
||||||
|
dbus-daemon --system
|
||||||
|
for _ in 1 2 3 4 5; do [ -S /run/dbus/system_bus_socket ] && break; sleep 1; done
|
||||||
|
|
||||||
|
avahi-daemon --daemonize --no-chroot
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
pids=""
|
||||||
|
for n in "$BASE_DOMAIN" "auth.$BASE_DOMAIN" "packwiz.$BASE_DOMAIN" "mc.$BASE_DOMAIN"; do
|
||||||
|
echo "mDNS publish: $n -> $HOST_LAN_IP"
|
||||||
|
avahi-publish -a "$n" "$HOST_LAN_IP" &
|
||||||
|
pids="$pids $!"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Block on the publishers; exit (→ restart) if one drops.
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
wait -n $pids 2>/dev/null || wait
|
||||||
Reference in New Issue
Block a user