Commit Graph

23 Commits

Author SHA1 Message Date
ab3d2c201b feat(ingress): public distribution.${BASE_DOMAIN} static vhost
Serve a static site at distribution.${BASE_DOMAIN} whose web root lives in
another repo (DISTRIBUTION_WEB_ROOT, bind-mounted read-only into caddy):
  - caddy/conf.d/30-distribution.caddy  file_server vhost
  - docker-compose.distribution.yml     mount snippet + external web root
  - issue-letsencrypt.sh / .env.example add distribution to LE_SUBDOMAINS
  - ulicraft-caddy.conf.tmpl            TLS-front block proxying to caddy

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 00:30:27 +02:00
3d52951355 feat(landing): pixel design ported to static Astro + en/es/eu i18n
Adopt the "Carved from stone" pixel design (landing/design/) as the apex
onboarding page, ported from its React/Babel-via-CDN prototype to static
Astro so it works on an offline LAN. Real modded-LAN content replaces the
prototype's fictional public-SMP copy.

- Vendor web fonts locally (tooling/fetch-fonts.sh -> public/fonts/) so the
  page renders without the Google Fonts CDN at party time.
- Port the design system (main.css: mood/hero/bevels) and split markup into
  Astro components (Creeper, PixelIcon, CopyChip, ServerListPanel).
- site.ts holds language-neutral config + theme knobs (mood/hero/headFont/
  dust) that replace the design's in-browser TweaksPanel; LITERALS holds
  never-translated product/in-game terms.
- i18n: English (/), Spanish (/es/), Euskera (/eu/) generated from one
  [...lang].astro via getStaticPaths; copy lives in src/i18n/ui.ts. Nav has
  an EN/ES/EU switcher; html lang + hreflang set per page.
- Status panel shows a static server-list row + honest stat tiles (no fake
  live count). Copy + scroll-reveal are the only client JS.

Build emits to ../www (gitignored). Euskera strings pending a native review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 18:18:36 +02:00
843347ad00 feat(tls): Let's Encrypt via OVH DNS-01 + host nginx vhost
tooling/issue-letsencrypt.sh: manual script, issues one cert per name
(apex + LE_SUBDOMAINS) with acme.sh + OVH DNS-01 (no inbound ports),
installs to certs/<name>/ and reloads nginx. nginx/ulicraft.conf.tmpl:
TLS vhosts for apex/pack (static) + auth (proxy to drasl). OVH creds and
LE_EMAIL in .env.example; certs/ gitignored. plan/15-letsencrypt.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:35:07 +02:00
4c874e20ed refactor(ingress): extract caddy to its own compose file; add nginx path
Caddy is no longer in the base stack. Two ingress paths now:
- docker-compose.caddy.yml — LAN/air-gap; build-stack.sh adds it for all
  up modes + the prep pre-bake. Holds the mcnet auth./pack. aliases.
- docker-compose.nginx.yml — production behind the host's nginx: publishes
  drasl on 127.0.0.1:25585, points minecraft at the host (extra_hosts) over
  HTTPS for pack + authlib.

Base loses the caddy service and minecraft's caddy depends_on (re-added by
caddy.yml). Blessing Skin override now requires caddy.yml (it only swaps
caddy's core conf).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:35:07 +02:00
6e91749f59 refactor(pack): template CustomSkinLoader + unify pack rendering
Add tooling/render-pack.sh: renders all pack/**/*.tmpl with ${BASE_DOMAIN}
(no dnsmasq HOST_LAN_IP coupling) and rebuilds the packwiz index. Both
render-config.sh and add-custom-mod.sh now delegate to it.

CustomSkinLoader.json's skin API roots are no longer frozen — it becomes
CustomSkinLoader.json.tmpl, rendered like the mod metadata. .packwizignore
broadened to *.tmpl; rendered .json gitignored as build output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:42:32 +02:00
f7858d4ec4 refactor(pack): template custom mod metadata so BASE_DOMAIN isn't frozen
The download URL is the only domain-dependent field in the external-file
metadata. Make mods/*.pw.toml build output rendered from committed
mods/*.pw.toml.tmpl (url uses ${BASE_DOMAIN}); render-config.sh and
add-custom-mod.sh render them + packwiz refresh at deploy/add time.

- pack/.packwizignore: keep *.pw.toml.tmpl out of the index
- gitignore rendered pack/mods/*.pw.toml + pack/index.toml (build output)
- seed a minimal index.toml before refresh (packwiz won't bootstrap one)
- add-custom-mod renders inline (BASE_DOMAIN only) — no coupling to
  dnsmasq's HOST_LAN_IP

Domain changes now just need a re-render, not a metadata rewrite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:07:35 +02:00
39be74d028 fix(pack): regenerate custom mod URLs for current BASE_DOMAIN
The mods/*.pw.toml download URLs were frozen at ulicraft.lan; the stack
now uses ulicraft.net. Regenerate all nine with the current domain.

add-custom-mod.sh: skip the copy when source == hosted dest (`-ef`),
so `add-custom-mod.sh custom --force` works as an in-place regen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:52:00 +02:00
c40cbe7594 refactor(pack): host custom jars from ./custom outside the pack root
Move pack/custom/ -> ./custom/ and bind-mount it into caddy at
/srv/pack/custom (served URL pack.${BASE_DOMAIN}/custom/ unchanged).
Keeping jars outside the packwiz pack root stops `packwiz refresh`
from indexing them as direct files on top of the mods/*.pw.toml
external refs (drops 9 bogus custom/*.jar entries from index.toml).

add-custom-mod.sh now writes jars to ./custom/. Trim the blessingskin
caddy override to just the conf swap (volumes merge by target).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:22:14 +02:00
2405eee57d feat(tooling): add-custom-mod.sh folder mode
Accept a directory: process every *.jar inside and run packwiz refresh
once at the end. --name rejected with a folder (names derived per-jar);
halts on an empty folder. Single-jar path unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 18:51:56 +02:00
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
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
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
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
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
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
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
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
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
c09da15bd0 initial commit 2026-05-24 04:03:42 +02:00