diff --git a/.gitignore b/.gitignore index e6e06c5..6c870ab 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ www/ landing/node_modules/ landing/.astro/ landing/dist/ + +# exported Caddy CA (per-deploy artifact) +caddy/caddy-root-ca.crt diff --git a/caddy/conf.d/10-static.caddy b/caddy/conf.d/10-static.caddy index 29c1712..2f87d44 100644 --- a/caddy/conf.d/10-static.caddy +++ b/caddy/conf.d/10-static.caddy @@ -1,6 +1,13 @@ # Static toggle — apex landing page + launcher downloads. # Mounted only when the stack runs with static files (build-stack.sh up static|full). http://{$BASE_DOMAIN} { + # Caddy's local CA root, so guests can trust the air-gap HTTPS mirror. + # Mounted from ./caddy/caddy-root-ca.crt (exported by build-stack prep; + # the live pki dir is root-only 0600 and can't be served directly). + handle /ca.crt { + root * /srv/ca-pub + file_server + } # Launcher downloads are a sibling mount (/srv/launcher), not nested under # the read-only /srv/www. handle_path strips the /launcher prefix. handle_path /launcher/* { diff --git a/docker-compose.static.yml b/docker-compose.static.yml index c8fbcfa..97f503d 100644 --- a/docker-compose.static.yml +++ b/docker-compose.static.yml @@ -8,3 +8,4 @@ services: - ./caddy/conf.d/10-static.caddy:/etc/caddy/conf.d/10-static.caddy:ro - ./www:/srv/www:ro - ./mirror/launcher:/srv/launcher:ro + - ./caddy/caddy-root-ca.crt:/srv/ca-pub/ca.crt:ro diff --git a/landing/src/data/site.ts b/landing/src/data/site.ts index 19f4a3e..f6ebe61 100644 --- a/landing/src/data/site.ts +++ b/landing/src/data/site.ts @@ -18,6 +18,9 @@ export const site = { // packwiz modpack entrypoint. packwizUrl: `http://packwiz.${BASE_DOMAIN}/pack.toml`, + // Caddy local CA root — guests import this to trust the offline asset mirror. + caCertUrl: `http://${BASE_DOMAIN}/ca.crt`, + // Launcher downloads. Stable filenames are symlinks created by // tooling/fetch-launcher.sh — keep these in sync with that script. launcher: { diff --git a/landing/src/pages/index.astro b/landing/src/pages/index.astro index ade2e04..56d7105 100644 --- a/landing/src/pages/index.astro +++ b/landing/src/pages/index.astro @@ -50,6 +50,11 @@ const { launcher } = site; Need credentials? Register at {site.authUrl}, then log in with that username and password.

+

+ Offline party? Download and trust the + local CA certificate so the game-file + mirror works over HTTPS. +

  • diff --git a/tooling/build-stack.sh b/tooling/build-stack.sh index 7fce11b..5512b3b 100755 --- a/tooling/build-stack.sh +++ b/tooling/build-stack.sh @@ -109,7 +109,32 @@ up() { log "PHASE up (mode=$mode)" have_script render-config.sh tooling/render-config.sh # cheap; ensures configs match current .env + + # Static mode mounts ./caddy/caddy-root-ca.crt as a file at /srv/ca-pub/ca.crt. + # Pre-create it (empty) so Docker doesn't make a directory at that path; the + # real cert is exported below once Caddy's local CA exists. + case "$mode" in + static|full) [ -e caddy/caddy-root-ca.crt ] || : > caddy/caddy-root-ca.crt ;; + esac + "${COMPOSE[@]}" "${files[@]}" up -d + + # Mirror/full provision Caddy's local CA — export it so guests can trust the + # HTTPS asset mirror (served at http://${BASE_DOMAIN}/ca.crt in static/full). + case "$mode" in + mirror|full) + local i + for i in 1 2 3 4 5; do + docker exec caddy cat /data/caddy/pki/authorities/local/root.crt \ + > caddy/caddy-root-ca.crt 2>/dev/null && break + sleep 1 + done + [ -s caddy/caddy-root-ca.crt ] \ + && echo " exported Caddy CA → caddy/caddy-root-ca.crt (served at /ca.crt)" \ + || warn "Caddy CA not ready; export later: docker exec caddy cat /data/caddy/pki/authorities/local/root.crt > caddy/caddy-root-ca.crt" + ;; + esac + log "stack up (mode=$mode). apex: http://${BASE_DOMAIN} auth: http://auth.${BASE_DOMAIN}" }