From d6e7504d6e87674253f19e1c38f8840af68721cd Mon Sep 17 00:00:00 2001 From: Oier Bravo Urtasun Date: Sun, 24 May 2026 05:07:20 +0200 Subject: [PATCH] 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) --- docker-compose.mirror.yml | 12 ++++++++++++ docker-compose.static.yml | 10 ++++++++++ docker-compose.yml | 11 ++++++----- tooling/build-stack.sh | 32 +++++++++++++++++++++++++------- 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 docker-compose.mirror.yml create mode 100644 docker-compose.static.yml diff --git a/docker-compose.mirror.yml b/docker-compose.mirror.yml new file mode 100644 index 0000000..77d46ee --- /dev/null +++ b/docker-compose.mirror.yml @@ -0,0 +1,12 @@ +# Mirror toggle — full client air-gap upstream mirror (see plan/11). +# Layer on top of the base: `docker compose -f docker-compose.yml -f docker-compose.mirror.yml up -d` +# (or `tooling/build-stack.sh --up mirror`). Adds the mirror vhost snippet, the +# upstream content mount, and publishes :443 for Caddy's `tls internal` certs. +# Populate the mirror first: tooling/mirror-airgap.sh (+ the proxy-capture step). +services: + caddy: + ports: + - "443:443" + volumes: + - ./caddy/conf.d/20-mirror.caddy:/etc/caddy/conf.d/20-mirror.caddy:ro + - ./mirror/upstream:/srv/mirror:ro diff --git a/docker-compose.static.yml b/docker-compose.static.yml new file mode 100644 index 0000000..c8fbcfa --- /dev/null +++ b/docker-compose.static.yml @@ -0,0 +1,10 @@ +# Static toggle — apex landing page + launcher downloads. +# Layer on top of the base: `docker compose -f docker-compose.yml -f docker-compose.static.yml up -d` +# (or `tooling/build-stack.sh --up static`). Adds the static vhost snippet plus +# the www + launcher content mounts. Build www first: cd landing && pnpm run build. +services: + caddy: + volumes: + - ./caddy/conf.d/10-static.caddy:/etc/caddy/conf.d/10-static.caddy:ro + - ./www:/srv/www:ro + - ./mirror/launcher:/srv/launcher:ro diff --git a/docker-compose.yml b/docker-compose.yml index 116aadc..2a612ca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,27 +29,28 @@ services: # HTTP_USER: "admin" # HTTP_PASS: "change-me" + # Core ingress. Static site + air-gap mirror are layered in via override + # files (docker-compose.static.yml / .mirror.yml) — see build-stack.sh --up. caddy: image: caddy:alpine container_name: caddy restart: unless-stopped ports: - "80:80" - - "443:443" # tls internal — air-gap mirror vhosts (see 11) environment: BASE_DOMAIN: ${BASE_DOMAIN} volumes: - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro - - ./www:/srv/www:ro + - ./caddy/conf.d/00-core.caddy:/etc/caddy/conf.d/00-core.caddy:ro - ./pack:/srv/pack:ro - - ./mirror/launcher:/srv/launcher:ro - - ./mirror/upstream:/srv/mirror:ro # byte-exact upstream mirror (see 11) networks: mcnet: + # All subdomain aliases live here (harmless when a vhost snippet isn't + # mounted; lets internal containers resolve them to Caddy). The spoof + # hosts only actually serve content when the mirror snippet is present. aliases: - "auth.${BASE_DOMAIN}" - "packwiz.${BASE_DOMAIN}" - # Air-gap spoof hosts -> Caddy, so internal containers resolve them too. - "meta.prismlauncher.org" - "piston-meta.mojang.com" - "piston-data.mojang.com" diff --git a/tooling/build-stack.sh b/tooling/build-stack.sh index 5cf3dff..30e2d8a 100755 --- a/tooling/build-stack.sh +++ b/tooling/build-stack.sh @@ -80,28 +80,46 @@ prep() { } # ---- offline bring-up ------------------------------------------------------ +# Modes select which optional layers come up (override files): +# core base only (dnsmasq, drasl, minecraft, mc-backup, caddy auth+packwiz) +# static + apex landing page + launcher downloads +# mirror + full air-gap upstream mirror (tls internal on :443) +# full static + mirror (default) up() { - log "PHASE up (offline-capable bring-up)" + local mode="${1:-full}" + local -a files=(-f docker-compose.yml) + case "$mode" in + core) ;; + static) files+=(-f docker-compose.static.yml) ;; + mirror) files+=(-f docker-compose.mirror.yml) ;; + full) files+=(-f docker-compose.static.yml -f docker-compose.mirror.yml) ;; + *) die "unknown up mode: '$mode' (use core|static|mirror|full)" ;; + esac + log "PHASE up (mode=$mode)" have_script render-config.sh tooling/render-config.sh # cheap; ensures configs match current .env - "${COMPOSE[@]}" up -d - log "stack up. apex: http://${BASE_DOMAIN} auth: http://auth.${BASE_DOMAIN}" + "${COMPOSE[@]}" "${files[@]}" up -d + log "stack up (mode=$mode). apex: http://${BASE_DOMAIN} auth: http://auth.${BASE_DOMAIN}" } # ---- dispatch -------------------------------------------------------------- preflight case "${1:-}" in --prep) prep ;; - --up) up ;; + --up) up "${2:-full}" ;; "") cat <