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>
68 lines
2.8 KiB
Markdown
68 lines
2.8 KiB
Markdown
# TLS — Let's Encrypt (OVH DNS-01) + host nginx ingress
|
|
|
|
Production serves real, publicly-trusted certs via the **host's own nginx**.
|
|
nginx terminates TLS and reverse-proxies every vhost to the caddy container
|
|
(published localhost-only on `${CADDY_HTTP_PORT}`) by Host header. caddy is the
|
|
internal router; nginx is the public TLS terminator. This is the only ingress
|
|
path — there are no compose overrides.
|
|
|
|
## Certs: one per name, via OVH DNS-01
|
|
|
|
`tooling/issue-letsencrypt.sh` issues a **separate** cert for the apex and each
|
|
subdomain (`${BASE_DOMAIN}`, `auth.…`, `pack.…`, plus the rest of
|
|
`LE_SUBDOMAINS`) using acme.sh + the OVH DNS-01 challenge — no inbound ports
|
|
needed, so it works regardless of public reachability.
|
|
|
|
### One-time setup
|
|
|
|
1. Install acme.sh:
|
|
```bash
|
|
curl https://get.acme.sh | sh -s email=you@example.com
|
|
```
|
|
2. OVH API credentials → `.env` (see `.env.example` `OVH_*`, `LE_EMAIL`,
|
|
`LE_SUBDOMAINS`). Create a token at <https://eu.api.ovh.com/createToken/> with
|
|
`GET/POST/PUT/DELETE` on `/domain/zone/*`, or leave `OVH_CK` blank and run the
|
|
script once — acme.sh prints an authorization URL; visit it, then paste the
|
|
consumer key into `OVH_CK` and re-run.
|
|
|
|
### Issue
|
|
|
|
```bash
|
|
tooling/issue-letsencrypt.sh # real certs
|
|
LE_STAGING=1 tooling/issue-letsencrypt.sh # dry run against the LE staging CA
|
|
```
|
|
|
|
Certs install to `certs/<name>/{cert.pem,key.pem}` (gitignored). acme.sh adds a
|
|
cron for renewal; `--reloadcmd` reloads nginx automatically on renew. Override
|
|
the reload with `RELOAD_CMD=...` if nginx isn't systemd-managed.
|
|
|
|
## nginx
|
|
|
|
1. Bring the stack up (caddy publishes on `127.0.0.1:${CADDY_HTTP_PORT}`):
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
2. Render + install the vhost (`nginx/ulicraft-caddy.conf.tmpl`):
|
|
```bash
|
|
tooling/render-nginx.sh --install
|
|
```
|
|
This substitutes `$BASE_DOMAIN $APP_DIR $CADDY_HTTP_PORT`, writes to
|
|
`sites-available`, symlinks `sites-enabled`, runs `nginx -t`, and reloads
|
|
nginx. nginx then terminates TLS per vhost (certs under `$APP_DIR/certs`) and
|
|
reverse-proxies each Host to caddy on `127.0.0.1:${CADDY_HTTP_PORT}`. Ensure
|
|
`www-data` can read `$APP_DIR/certs`.
|
|
|
|
## DNS
|
|
|
|
Point the public DNS for `${BASE_DOMAIN}` and every subdomain
|
|
(`auth.` `pack.` `avatar.` `status.` `distribution.` `www.`) at the host running
|
|
nginx. DNS is configured **outside this repo**. The Minecraft container reaches
|
|
the stack's own names via caddy's `mcnet` aliases, not public DNS.
|
|
|
|
## Why DNS-01 (not HTTP-01)
|
|
|
|
DNS-01 only needs the OVH API, so it issues regardless of public reachability —
|
|
and `ulicraft.net` is a real OVH-managed domain, which LE requires (it never
|
|
issues for `.lan`/`.local`). HTTP-01/TLS-ALPN-01 would need public inbound on
|
|
80/443. The JVM trusts the resulting Let's Encrypt certs with no CA import.
|