Commit Graph

87 Commits

Author SHA1 Message Date
e1ccdda961 feat(tooling): add-custom-mod.sh — host local jars as packwiz external files
Copies a local jar under pack/custom/ (served by caddy), sha256s it,
writes pack/mods/<slug>.pw.toml per packwiz "Other external files",
then packwiz refresh. Cautious: halts on bad side, whitespace in
filename, or existing entry without --force.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 18:48:55 +02:00
5172316919 feat(auth): Blessing Skin variant as Drasl alternative
Override stack that swaps Drasl for Blessing Skin Server + MariaDB,
talking to Minecraft via the yggdrasil-api plugin (authlib endpoint
/api/yggdrasil, ONLINE_MODE=TRUE). Caddy auth.* repointed to
blessing-skin:80; Drasl left idle (compose merges depends_on).

Run: docker compose -f docker-compose.yml -f docker-compose.blessingskin.yml up -d

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 18:48:54 +02:00
c279f35e14 feat(dns): 'hosts' output + /etc/hosts simulation docs
dns-records.sh <mode> hosts prints a marker-wrapped /etc/hosts block to pipe
into /etc/hosts (single-machine testing without a DNS server). README documents
apply/remove + the airgap caveat (spoof hosts break real internet while present).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 14:23:14 +02:00
d8aefe95c4 feat(tooling): mdns-host-setup.sh — pin host avahi to the LAN NIC
Auto-detects the LAN interface from HOST_LAN_IP, sets allow-interfaces in
/etc/avahi/avahi-daemon.conf (idempotent, backs up), restarts avahi. Self-sudos.
Fixes the multi-bridge 'Local name collision' that blocks the mDNS path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 14:11:41 +02:00
3c2ce72c2a docs(plan): add 13-dns-and-run-modes; mark dnsmasq optional
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 06:06:33 +02:00
64f11c8120 feat(build-stack): mDNS preflight warnings (host avahi, dbus, interface count)
When ENABLE_MDNS=true, warn if BASE_DOMAIN isn't .local, host avahi-daemon
isn't running, the D-Bus socket is missing, or the host has many interfaces
(avahi self-collision risk → suggests allow-interfaces).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 06:05:44 +02:00
c7151b7333 fix(mdns): publish via host avahi over D-Bus (not a second daemon)
A container running its own avahi-daemon collides with the host's on :5353.
Instead publish to the host avahi over its mounted D-Bus socket using avahi-tools
(avahi-publish). Needs apparmor=unconfined (docker-default blocks the D-Bus
publish). Documented host prereqs incl. allow-interfaces for multi-bridge hosts.

Tested: publish reaches host avahi and registers the names; on hosts with many
docker bridges avahi self-collides until restricted to the LAN interface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 06:03:26 +02:00
de75a2ca1d docs: update README for .lan, online/airgap modes, party DNS + mDNS
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:57:26 +02:00
8eeda1265c 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>
2026-05-24 05:56:54 +02:00
f14578dc65 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>
2026-05-24 05:56:54 +02:00
390f8c78af feat(caddy): serve Caddy root CA at /ca.crt for guest trust
Air-gap mirror uses tls internal; guests must trust Caddy's local CA. Serve it
at http://<domain>/ca.crt from a world-readable mount (the live pki dir is
root-only 0600). build-stack --up mirror|full exports the CA after bring-up;
landing page links it. Pre-creates the mount target to avoid a dir bind.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:32:31 +02:00
b277fc6268 feat(build-stack): fetch authlib-injector.jar during prep
Server JVM agent needs runtime/authlib-injector.jar (gitignored); pull the
latest yushijinhun release if absent so pre-bake doesn't crash-loop on a
missing agent jar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:20:02 +02:00
4ddf36cefd docs: add README (stack summary + launch instructions)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:10:44 +02:00
1aed12bf00 fix(compose): scope upstream spoof aliases to mirror mode
The spoof aliases (maven.neoforged.net, libraries.minecraft.net, etc.) hijacked
those hostnames for every mcnet container, so the ONLINE NeoForge install during
pre-bake hit the empty mirror (cert path failure). Moved them to the mirror
override; core/static modes resolve the real upstreams.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:10:13 +02:00
2d7a7554bd fix(drasl): ApplicationOwner is a string, not a table (config parse crash)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:10:13 +02:00
df8561c798 feat(dnsmasq): SRV record so clients connect to mc.<domain> without a port
Minecraft is a custom TCP protocol, not HTTP, so the no-port UX is solved with
a DNS SRV record (_minecraft._tcp.mc.<domain> -> :25565) rather than an HTTP
reverse proxy. Landing page now shows the bare address.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:08:07 +02:00
d6e7504d6e feat(compose): optional static/mirror via override files; build-stack up modes
Base compose is core only (dnsmasq, drasl, minecraft, mc-backup, caddy
auth+packwiz). docker-compose.static.yml and docker-compose.mirror.yml layer
on the landing site and the air-gap mirror independently. build-stack.sh --up
[core|static|mirror|full] selects the override files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:07:20 +02:00
3bf714a224 refactor(caddy): split vhosts into conf.d snippets (core/static/mirror)
Base Caddyfile now imports conf.d/*.caddy. Snippets are mounted selectively
so the stack runs with or without the static site / air-gap mirror:
  00-core   auth + packwiz (always)
  10-static apex landing + launcher downloads
  20-mirror air-gap upstream hosts (tls internal)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:07:20 +02:00
78e92a65be fix(caddy): serve launcher from sibling mount, not nested under /srv/www
Mounting ./mirror/launcher at /srv/www/launcher failed: /srv/www is a
read-only mount, so the nested mountpoint can't be created. Mount it at
/srv/launcher and route /launcher/* via handle_path instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:04:59 +02:00
eede0102c6 fix(tooling): fetch-launcher Windows stable symlink picks MSVC Setup x64
MSVC and MinGW Setup .exe both matched 'setup.*.exe'; tightened the
include pattern to 'msvc-setup.*.exe' so exactly one candidate resolves.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 05:02:02 +02:00
f513f60766 feat(caddy): add tls internal vhosts for upstream mirror hosts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:47:38 +02:00
a6c4d3be8c feat(dnsmasq): add air-gap spoof records for upstream hosts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:47:10 +02:00
33eb5c60e6 feat(tooling): add mirror-airgap.sh (deterministic mirror + capture notice)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:47:02 +02:00
a6a43a17ac feat(tooling): add fetch-launcher.sh (all platforms + stable symlinks)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:44:27 +02:00
8f6d846858 refactor(compose): minecraft via PACKWIZ_URL, authlib->auth., runtime mount
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:42:55 +02:00
31eadcfb32 refactor(runtime): rename extras/ to runtime/, drop obsolete modrinth list
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:42:19 +02:00
5f7a197c56 feat(tooling): add mirror-mods.sh (vendor jars + rewrite .pw.toml URLs)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:40:56 +02:00
7f10cb24c9 feat(pack): packwiz init (NeoForge 1.21.1) + curation README
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:40:04 +02:00
0446fc68ac refactor(compose): drasl internal-only behind caddy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:38:53 +02:00
e61286d2b3 feat(drasl): add config.toml.tmpl (password login, SignPublicKeys=false)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:38:41 +02:00
e351736e2e feat(compose): add caddy service + network aliases
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:38:04 +02:00
6d09f659db feat(caddy): add Caddyfile (apex + auth + packwiz vhosts)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:34:33 +02:00
c717890012 feat(compose): add dnsmasq service
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:11:45 +02:00
b24814a214 feat(dnsmasq): add dnsmasq.conf.tmpl (wildcard *.BASE_DOMAIN)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:11:04 +02:00
1300a02070 feat(tooling): add render-config.sh (envsubst, halt on unset var)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:07:54 +02:00
26cbaa1bdf feat(env): add BASE_DOMAIN + HOST_LAN_IP to .env.example
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 04:06:56 +02:00
c09da15bd0 initial commit 2026-05-24 04:03:42 +02:00