refactor!: unify into one compose, drop airgap/mirror/dnsmasq/avahi/blessingskin

Collapse the override-file matrix into a single docker-compose.yml holding the
whole stack: drasl, minecraft, mc-backup, caddy, nmsr, uptime-kuma. Bring-up is
now just `docker compose up -d --build`.

Removed features (dead-ends for this deployment):
- airgap / full asset mirror (mirror-airgap.sh, mirror-mods.sh, 20-mirror.caddy,
  caddy local-CA export, /ca.crt)
- dnsmasq + avahi/mDNS + dns-records.sh + mdns-host-setup.sh + ENABLE_MDNS;
  DNS is now handled outside this repo (HOST_LAN_IP dropped)
- Blessing Skin auth variant (compose + 00-core-blessingskin.caddy + BS_* env)
- host-nginx-static variant (docker-compose.nginx.yml, nginx/ulicraft.conf.tmpl)
- build-stack.sh and its run modes (online/airgap/core)

Production ingress is the only path now: host nginx terminates TLS (LE certs)
in front of caddy on a localhost-only port; caddy routes every vhost by Host
header. Launcher downloads move mirror/launcher -> launcher/.

Docs: README, deploy skill, and plan/ rewritten to match; obsolete plan docs
(dnsmasq, blessing-skin, assets-mirror, full-airgap-mirror, dns-and-run-modes)
deleted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 02:14:09 +02:00
parent ff645de2c8
commit 67d1f82e6a
53 changed files with 522 additions and 2244 deletions

View File

@@ -1,19 +1,17 @@
# ──────────────────────────────────────────────────────────────────
# Ulicraft host nginx — TLS terminator in FRONT of caddy.
# ──────────────────────────────────────────────────────────────────
# Alternative to ulicraft.conf.tmpl. Instead of nginx serving the static
# files + proxying only drasl, here caddy (the docker container) is the single
# ingress for ALL vhosts and nginx just terminates TLS and reverse-proxies
# everything to caddy by Host header.
# caddy (in docker-compose.yml) is the single internal ingress for ALL vhosts;
# this host nginx terminates TLS and reverse-proxies everything to caddy by Host
# header. Prefer tooling/render-nginx.sh over hand-rendering.
#
# Caddy must be published on a localhost port — set in .env:
# CADDY_HTTP_PORT=8880
# CADDY_HTTP_BIND=127.0.0.1
# and the stack brought up with the caddy override (NOT the nginx override):
# docker compose -f docker-compose.yml -f docker-compose.caddy.yml \
# -f docker-compose.static.yml up -d
# and the stack brought up:
# docker compose up -d
#
# Render with BOTH vars then install:
# Render with the vars then install:
# CADDY_HTTP_PORT=8880 BASE_DOMAIN=ulicraft.net APP_DIR=/home/ubuntu/mc/ulicraft-server-v1 \
# envsubst '$CADDY_HTTP_PORT $BASE_DOMAIN $APP_DIR' \
# < nginx/ulicraft-caddy.conf.tmpl | sudo tee /etc/nginx/sites-available/ulicraft.conf

View File

@@ -1,93 +0,0 @@
# ──────────────────────────────────────────────────────────────────
# Ulicraft host nginx — TLS ingress with Let's Encrypt certs.
# ──────────────────────────────────────────────────────────────────
# Template. Render with BOTH vars then install:
#
# APP_DIR=/home/ubuntu/mc/ulicraft-server-v1 BASE_DOMAIN=ulicraft.net \
# envsubst '$APP_DIR $BASE_DOMAIN' \
# < nginx/ulicraft.conf.tmpl | sudo tee /etc/nginx/sites-available/ulicraft.conf
# sudo ln -sf /etc/nginx/sites-available/ulicraft.conf /etc/nginx/sites-enabled/
# sudo nginx -t && sudo systemctl reload nginx
#
# Prereqs:
# - certs issued: tooling/issue-letsencrypt.sh -> $APP_DIR/certs/<name>/{cert,key}.pem
# - the docker stack up with the nginx override (publishes drasl on 127.0.0.1:25585):
# docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d
# - nginx's user (www-data) can READ $APP_DIR/{www,pack,custom,certs}
# ──────────────────────────────────────────────────────────────────
# HTTP -> HTTPS for every name.
server {
listen 80;
listen [::]:80;
server_name ${BASE_DOMAIN} auth.${BASE_DOMAIN} pack.${BASE_DOMAIN};
return 301 https://$host$request_uri;
}
# Apex — static landing page (./www) + launcher downloads (./mirror/launcher).
# /ca.crt from the caddy path is intentionally omitted: LE certs are publicly
# trusted, so guests need no CA import.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${BASE_DOMAIN};
ssl_certificate ${APP_DIR}/certs/${BASE_DOMAIN}/cert.pem;
ssl_certificate_key ${APP_DIR}/certs/${BASE_DOMAIN}/key.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Launcher downloads (populated by tooling/fetch-launcher.sh -> ./mirror/launcher).
location /launcher/ {
alias ${APP_DIR}/mirror/launcher/;
autoindex on;
}
location / {
root ${APP_DIR}/www;
index index.html;
try_files $uri $uri/ =404;
}
}
# Pack — packwiz metadata (./pack) + custom jars (./custom at /custom/).
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pack.${BASE_DOMAIN};
ssl_certificate ${APP_DIR}/certs/pack.${BASE_DOMAIN}/cert.pem;
ssl_certificate_key ${APP_DIR}/certs/pack.${BASE_DOMAIN}/key.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Locally-hosted custom mod jars live outside ./pack; expose them at /custom/.
location /custom/ {
alias ${APP_DIR}/custom/;
autoindex on;
}
location / {
root ${APP_DIR}/pack;
autoindex on;
}
}
# Auth — reverse proxy to drasl (published on localhost by the nginx override).
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name auth.${BASE_DOMAIN};
ssl_certificate ${APP_DIR}/certs/auth.${BASE_DOMAIN}/cert.pem;
ssl_certificate_key ${APP_DIR}/certs/auth.${BASE_DOMAIN}/key.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
client_max_body_size 4m; # skin uploads
location / {
proxy_pass http://127.0.0.1:25585;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}