feat(dns): party-DNS records generator + online/airgap modes

DNS is now your own party server. tooling/dns-records.sh prints the records
(online = service names; airgap = + Mojang/launcher/NeoForge spoofs) in several
formats. build-stack --up online|airgap selects the mirror layer and prints the
matching records. dnsmasq moved to an optional override (docker-compose.dnsmasq.yml).
Default domain switched to .lan (.local is hijacked by mDNS on unicast DNS).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 05:56:54 +02:00
parent 390f8c78af
commit f14578dc65
5 changed files with 144 additions and 46 deletions

View File

@@ -1,8 +1,10 @@
# ──────────────────────────────────────────────────────────────────
# Ulicraft LAN-party stack — Minecraft 1.21.1 NeoForge + Drasl auth
# ──────────────────────────────────────────────────────────────────
# Topology (single source of config: BASE_DOMAIN + HOST_LAN_IP in .env):
# - dnsmasq resolves *.${BASE_DOMAIN} -> HOST_LAN_IP for guest laptops
# Single source of config: BASE_DOMAIN + HOST_LAN_IP in .env.
# DNS is provided by YOUR party DNS server — see tooling/dns-records.sh for the
# records to add (online vs airgap). A turnkey dnsmasq is available as an
# optional layer: docker-compose.dnsmasq.yml.
# - caddy is the only HTTP ingress; holds mcnet aliases so the stack
# resolves auth.${BASE_DOMAIN} / packwiz.${BASE_DOMAIN} internally too
# - drasl handles auth (password login; NO Keycloak/OIDC in this stack)
@@ -11,24 +13,6 @@
# ──────────────────────────────────────────────────────────────────
services:
dnsmasq:
image: jpillora/dnsmasq
container_name: dnsmasq
restart: unless-stopped
ports:
# Bind DNS to the host LAN IP so it doesn't clash with systemd-resolved on :53.
- "${HOST_LAN_IP}:53:53/udp"
- "${HOST_LAN_IP}:53:53/tcp"
volumes:
- ./dnsmasq/dnsmasq.conf:/etc/dnsmasq.conf:ro
networks:
- mcnet
# The webproc UI (:8080) can be exposed later behind Caddy as dns.${BASE_DOMAIN};
# guard it with HTTP_USER / HTTP_PASS env vars.
# environment:
# HTTP_USER: "admin"
# HTTP_PASS: "change-me"
# Core ingress. Static site + air-gap mirror are layered in via override
# files (docker-compose.static.yml / .mirror.yml) — see build-stack.sh --up.
caddy: