From 3c2ce72c2ad0827009139ba53ff382de068bfc54 Mon Sep 17 00:00:00 2001 From: Oier Bravo Urtasun Date: Sun, 24 May 2026 06:06:33 +0200 Subject: [PATCH] docs(plan): add 13-dns-and-run-modes; mark dnsmasq optional Co-Authored-By: Claude Opus 4.7 (1M context) --- plan/00-overview.md | 2 ++ plan/01-dnsmasq.md | 6 ++++ plan/13-dns-and-run-modes.md | 65 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 plan/13-dns-and-run-modes.md diff --git a/plan/00-overview.md b/plan/00-overview.md index de3d165..24205bf 100644 --- a/plan/00-overview.md +++ b/plan/00-overview.md @@ -116,6 +116,8 @@ PARTY (air-gapped): - `09-landing.md` — Astro+TS guest onboarding page → www/ - `10-assets-mirror.md` — lighter alternative: objects-only Fjord Assets Server override - `11-full-airgap-mirror.md` — CHOSEN: DNS+TLS transparent mirror for full client air-gap +- `12-build-order.md` — commit-per-task build sequence +- `13-dns-and-run-modes.md` — domain (.lan), online/airgap modes, party DNS, mDNS option ## Boot/dependency order diff --git a/plan/01-dnsmasq.md b/plan/01-dnsmasq.md index 377d44b..9808690 100644 --- a/plan/01-dnsmasq.md +++ b/plan/01-dnsmasq.md @@ -1,5 +1,11 @@ # dnsmasq — LAN wildcard DNS +> **SUPERSEDED for the default path — see `13-dns-and-run-modes.md`.** DNS is now +> your own party server (records via `tooling/dns-records.sh`); dnsmasq moved to +> an optional turnkey layer (`docker-compose.dnsmasq.yml`). Default domain is +> `.lan` (not `.local`). The wildcard/spoof template below still applies when you +> opt into dnsmasq. + ## Summary Provides name resolution for guest laptops so `*.ulicraft.local` resolves to the diff --git a/plan/13-dns-and-run-modes.md b/plan/13-dns-and-run-modes.md new file mode 100644 index 0000000..853504d --- /dev/null +++ b/plan/13-dns-and-run-modes.md @@ -0,0 +1,65 @@ +# DNS strategy + run modes + +How names resolve and which layers come up. Supersedes the "dnsmasq is core" +assumption in `01-dnsmasq.md`. + +## Domain: `.lan`, not `.local` + +`BASE_DOMAIN=ulicraft.lan` by default. `.local` is intercepted by mDNS on +macOS/Linux and does **not** resolve through a normal unicast DNS server +(that was the `DNS_PROBE_FINISHED_NXDOMAIN`). Use `.local` only with the mDNS +path below. + +## Run modes — `tooling/build-stack.sh --up ` + +| Mode | Compose layers | Use | +|---|---|---| +| `online` | base + static | internet present; landing + launcher; no mirror | +| `airgap` | base + static + mirror | no internet; full asset mirror on `:443` (default) | +| `core` | base | debugging | + +Base = drasl, minecraft, mc-backup, caddy(auth+packwiz). `static` = apex landing + +launcher + `/ca.crt`. `mirror` = upstream spoof vhosts (`tls internal`) + `:443` + +caddy aliases. `--up` prints the DNS records for the chosen mode. + +## DNS: your own party server (primary) + +You run the party DNS. Generate records with `tooling/dns-records.sh `: +- `online` → service names (`${BASE_DOMAIN}`, `auth.`, `packwiz.`, `mc.`) → `HOST_LAN_IP` +- `airgap` → the above **plus** the spoofed upstreams (`meta.prismlauncher.org`, + `piston-meta`/`piston-data.mojang.com`, `libraries.minecraft.net`, + `maven.neoforged.net`, `resources.download.minecraft.net`) → `HOST_LAN_IP` + +Output formats: plain, `/etc/hosts`, BIND zone, dnsmasq `address=`, plus the +Minecraft SRV line. Minecraft needs no port (`mc.${BASE_DOMAIN}` defaults to 25565). + +## Optional resolver layers + +- **dnsmasq** (`docker-compose.dnsmasq.yml`) — turnkey DNS if you don't run your + own. Binds `${HOST_LAN_IP}:53`. Serves the rendered `dnsmasq/dnsmasq.conf` + (wildcard + airgap spoofs). +- **mDNS / Avahi** (`docker-compose.avahi.yml`, `ENABLE_MDNS=true`) — zero-config + `.local` for guests (macOS/Linux native; Windows needs Bonjour). See below. + +## mDNS path (ENABLE_MDNS=true + BASE_DOMAIN=*.local) + +The `avahi` container publishes the service names to the **host's** avahi-daemon +over its D-Bus socket (it does NOT run its own daemon — that collides with the +host on `:5353`). + +Requirements / gotchas (build-stack warns on these): +- host runs `avahi-daemon`; `/run/dbus/system_bus_socket` mounted in. +- `security_opt: apparmor=unconfined` on the container (docker-default AppArmor + blocks the D-Bus publish). +- multi-interface hosts (e.g. many docker bridges) → avahi self-collides + ("Local name collision"); set `allow-interfaces=` in + `/etc/avahi/avahi-daemon.conf`. +- mDNS resolves **only** `.local`, so it cannot serve the air-gap upstream + spoofs (real public hostnames) — those always need real DNS. + +## Status (tested 2026-05-24) + +- `.lan` + own-DNS path: verified end-to-end (apex/auth/packwiz/ca.crt/mirror + all 200, minecraft healthy). +- mDNS publish mechanism: verified reaching host avahi; full green-light blocked + on this dev box only by its 38 docker bridges (allow-interfaces fixes it).