Files
ulicraft-server-v1/plan/01-dnsmasq.md
2026-05-24 04:03:42 +02:00

2.5 KiB

dnsmasq — LAN wildcard DNS

Summary

Provides name resolution for guest laptops so *.ulicraft.local resolves to the Docker host. Replaces the homelab's AdGuard (dropped for the LAN party). Image: jpillora/dnsmasq (dnsmasq wrapped in webproc, optional web UI on :8080).

Config is a file, not env-driven — /etc/dnsmasq.conf, standard dnsmasq format. Rendered from a template by tooling/render-config.sh.

Only guest laptops point their DNS here. Stack-internal resolution is handled by Docker network aliases on Caddy (see 02-caddy.md), so dnsmasq is not on the critical path for the server's own services.

Config template

dnsmasq/dnsmasq.conf.tmpl:

# wildcard: every *.ulicraft.local → host LAN IP
address=/${BASE_DOMAIN}/${HOST_LAN_IP}
# upstream optional; party is offline so may be omitted
no-resolv

Air-gap spoof records (see 11)

For full client air-gap, this file also spoofs the real upstream hosts → our Caddy mirror (piston-meta/piston-data/libraries.minecraft.net/ maven.neoforged.net/resources.download.minecraft.net/meta.prismlauncher.org). Full list + rationale in 11-full-airgap-mirror.md. Keep in sync with the capture step. Auth hosts (session/textures/api.mojang) are NOT spoofed — drasl handles those via authlib-injector.

Gotcha — port 53 conflict

Linux Docker hosts usually run systemd-resolved bound to :53. Publishing 53:53 will fail with address already in use. Resolve by one of:

  • Bind dnsmasq only to the LAN IP: publish ${HOST_LAN_IP}:53:53/udp (+tcp)
  • Or disable resolved's stub listener (DNSStubListener=no) and restart resolved

Gotcha — .local / mDNS

See overview. Avahi may shortcut *.local to multicast before hitting dnsmasq. Test on a macOS client early; if broken, switch BASE_DOMAIN to .lan.

Tasks

  • Add dnsmasq service to docker-compose.yml (jpillora/dnsmasq)
  • Create dnsmasq/dnsmasq.conf.tmpl with wildcard address= line
  • Wire render-config.sh to emit dnsmasq/dnsmasq.conf (gitignored)
  • Decide port-53 strategy (bind to HOST_LAN_IP vs disable resolved stub)
  • Publish 53/udp + 53/tcp; mount rendered conf read-only
  • Optionally expose webproc UI (8080) behind Caddy as dns.ulicraft.local
  • Document guest DNS setting (set DNS server = HOST_LAN_IP)
  • Verify *.local resolves on Windows + macOS + Linux guests (mDNS check)
  • Add air-gap spoof address= records (see 11) once capture confirms the host list