docs: update README for .lan, online/airgap modes, party DNS + mDNS
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
102
README.md
102
README.md
@@ -1,9 +1,9 @@
|
|||||||
# Ulicraft Server
|
# Ulicraft Server
|
||||||
|
|
||||||
Self-hosted modded Minecraft (NeoForge 1.21.1) for a LAN party, designed to run
|
Self-hosted modded Minecraft (NeoForge 1.21.1) for a LAN party. Runs **online**
|
||||||
**fully offline**. Self-hosted auth/skins (Drasl), a packwiz modpack, a guest
|
(internet present) or **fully air-gapped** (offline). Self-hosted auth/skins
|
||||||
landing page, and a transparent mirror of Mojang/launcher assets so guest
|
(Drasl), a packwiz modpack, a guest landing page, and a transparent mirror of
|
||||||
laptops need no internet.
|
Mojang/launcher/NeoForge assets so guest laptops need no internet.
|
||||||
|
|
||||||
## Stack
|
## Stack
|
||||||
|
|
||||||
@@ -11,67 +11,79 @@ laptops need no internet.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `minecraft` | itzg/minecraft-server | NeoForge 1.21.1 server, `:25565` |
|
| `minecraft` | itzg/minecraft-server | NeoForge 1.21.1 server, `:25565` |
|
||||||
| `drasl` | unmojang/drasl | Yggdrasil auth + skins (password login) |
|
| `drasl` | unmojang/drasl | Yggdrasil auth + skins (password login) |
|
||||||
| `caddy` | caddy:alpine | ingress: landing page, auth/packwiz proxy, asset mirror |
|
| `caddy` | caddy:alpine | ingress: landing, auth/packwiz proxy, asset mirror (`tls internal`) |
|
||||||
| `dnsmasq` | jpillora/dnsmasq | LAN DNS `*.ulicraft.local` + Minecraft SRV |
|
|
||||||
| `mc-backup` | itzg/mc-backup | world backups every 6h via RCON |
|
| `mc-backup` | itzg/mc-backup | world backups every 6h via RCON |
|
||||||
|
|
||||||
Everything keys off two vars in `.env`: `BASE_DOMAIN` (default `ulicraft.local`)
|
Optional layers: `avahi` (mDNS `.local`), `dnsmasq` (turnkey DNS) — only if you
|
||||||
and `HOST_LAN_IP`. Services are subdomains: `auth.`, `packwiz.`, plus the apex
|
don't run your own DNS.
|
||||||
landing page.
|
|
||||||
|
Config lives in `.env`: `BASE_DOMAIN` (default `ulicraft.lan`), `HOST_LAN_IP`,
|
||||||
|
`RCON_PASSWORD`, `ENABLE_MDNS`. Services are subdomains: `auth.`, `packwiz.`,
|
||||||
|
`mc.`, plus the apex landing page.
|
||||||
|
|
||||||
|
## DNS (pick one)
|
||||||
|
|
||||||
|
Names must resolve to `HOST_LAN_IP`. Use **your own party DNS server** (recommended):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tooling/dns-records.sh online # service names only (internet present)
|
||||||
|
tooling/dns-records.sh airgap # + Mojang/launcher/NeoForge spoofs (offline)
|
||||||
|
```
|
||||||
|
Paste the printed records into your DNS. **Use `.lan`, not `.local`** — `.local`
|
||||||
|
is intercepted by mDNS and won't resolve via unicast DNS.
|
||||||
|
|
||||||
|
Alternatives: `ENABLE_MDNS=true` + `BASE_DOMAIN=*.local` (zero-config mDNS,
|
||||||
|
macOS/Linux native, Windows needs Bonjour) — but mDNS can't serve the air-gap
|
||||||
|
upstream spoofs. Or layer in `docker-compose.dnsmasq.yml` for a turnkey DNS.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Docker + Docker Compose, and for prep: `pnpm`, `packwiz`, `jq`, `curl`,
|
Docker + Docker Compose; for prep also `pnpm`, `packwiz`, `jq`, `curl`,
|
||||||
`envsubst`, `sha1sum`.
|
`envsubst`, `sha1sum`.
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cp .env.example .env # set BASE_DOMAIN, HOST_LAN_IP, RCON_PASSWORD
|
|
||||||
```
|
|
||||||
|
|
||||||
Point guest laptops' DNS at `HOST_LAN_IP` (resolves `*.ulicraft.local`). On the
|
|
||||||
Docker host, free port 53 if `systemd-resolved` holds it (dnsmasq binds the LAN
|
|
||||||
IP only).
|
|
||||||
|
|
||||||
## Launch
|
## Launch
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
tooling/build-stack.sh --prep # ONLINE, run once: render configs, build
|
cp .env.example .env # set BASE_DOMAIN, HOST_LAN_IP, RCON_PASSWORD
|
||||||
# landing, mirror mods+assets, fetch
|
|
||||||
# launcher, pre-bake the server volume
|
|
||||||
|
|
||||||
tooling/build-stack.sh --up [mode] # bring the stack up
|
tooling/build-stack.sh --prep # ONLINE, once: render, build landing,
|
||||||
# core base only (no static site, no mirror)
|
# mirror mods+assets, fetch launcher +
|
||||||
# static + apex landing page + launcher downloads
|
# authlib, pre-bake the server volume
|
||||||
# mirror + full air-gap asset mirror (HTTPS :443)
|
|
||||||
# full static + mirror (default)
|
tooling/build-stack.sh --up online # internet present, no mirror
|
||||||
|
tooling/build-stack.sh --up airgap # offline; full asset mirror on :443 (default)
|
||||||
|
tooling/build-stack.sh --up core # base only (debugging)
|
||||||
```
|
```
|
||||||
|
|
||||||
Down: `docker compose -f docker-compose.yml -f docker-compose.static.yml -f docker-compose.mirror.yml down`
|
`--up` prints the DNS records to add for that mode. Down:
|
||||||
|
`docker compose -f docker-compose.yml -f docker-compose.static.yml -f docker-compose.mirror.yml down`
|
||||||
|
|
||||||
## Join (guests)
|
## Join (guests)
|
||||||
|
|
||||||
1. Open `http://ulicraft.local`, download FjordLauncherUnlocked for your OS.
|
1. Open `http://ulicraft.lan`, download FjordLauncherUnlocked for your OS.
|
||||||
2. Add an **authlib-injector** account, URL `http://auth.ulicraft.local/authlib-injector`
|
2. Add an **authlib-injector** account, URL `http://auth.ulicraft.lan/authlib-injector`
|
||||||
(register/login at `http://auth.ulicraft.local`).
|
(register/login at `http://auth.ulicraft.lan`).
|
||||||
3. (Air-gap) Trust the Caddy root CA; in Settings → APIs set **Assets Server**
|
3. **Air-gap only:** trust the local CA — download `http://ulicraft.lan/ca.crt`
|
||||||
to the mirror if not using DNS spoofing.
|
and add it to your OS trust store (so the HTTPS asset mirror is trusted).
|
||||||
4. Import the pack: `http://packwiz.ulicraft.local/pack.toml`.
|
4. Import the pack: `http://packwiz.ulicraft.lan/pack.toml`.
|
||||||
5. Connect to **`mc.ulicraft.local`** (no port — SRV record).
|
5. Connect to **`mc.ulicraft.lan`** (no port needed).
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
docker-compose.yml + .static.yml + .mirror.yml # core + optional layers
|
docker-compose.yml # core: drasl, minecraft, mc-backup, caddy
|
||||||
caddy/Caddyfile + conf.d/*.caddy # ingress vhost snippets
|
.static.yml .mirror.yml # online/airgap layers
|
||||||
drasl/config/config.toml.tmpl # auth config (rendered)
|
.avahi.yml .dnsmasq.yml # optional DNS layers
|
||||||
dnsmasq/dnsmasq.conf.tmpl # LAN DNS + SRV (rendered)
|
caddy/Caddyfile + conf.d/*.caddy # ingress vhost snippets (core/static/mirror)
|
||||||
pack/ # packwiz modpack source
|
drasl/config/config.toml.tmpl # auth config (rendered)
|
||||||
landing/ # Astro site → www/
|
dnsmasq/dnsmasq.conf.tmpl # optional DNS config (rendered)
|
||||||
tooling/ # build-stack + render/mirror/fetch scripts
|
docker/avahi/ # mDNS responder image
|
||||||
mirror/ # vendored jars + launcher + asset mirror (gitignored)
|
pack/ # packwiz modpack source
|
||||||
plan/ # full design docs (00–12)
|
landing/ # Astro site → www/
|
||||||
|
tooling/ # build-stack, render-config, dns-records,
|
||||||
|
# mirror-mods, mirror-airgap, fetch-launcher
|
||||||
|
mirror/ # vendored jars + launcher + asset mirror (gitignored)
|
||||||
|
plan/ # full design docs (00–12)
|
||||||
```
|
```
|
||||||
|
|
||||||
See `plan/00-overview.md` for the full design.
|
See `plan/00-overview.md` for the full design.
|
||||||
|
|||||||
Reference in New Issue
Block a user