# Caddy — internal router behind host nginx ## Summary caddy is the stack's **internal HTTP router**, sitting behind the host's own nginx (which terminates TLS — see `15-letsencrypt.md`). caddy is published only on a localhost-only port (`CADDY_HTTP_BIND=127.0.0.1`, `CADDY_HTTP_PORT=8880`); nginx reverse-proxies every public vhost to it by Host header. Roles: 1. **Reverse proxy** — `auth.` → drasl, `avatar.` → nmsr, `status.` → uptime-kuma. 2. **Static** — apex serves the landing page + `/launcher/` downloads; `distribution.` serves a static site from another repo. Image: `caddy:alpine`. caddy natively reads `{$BASE_DOMAIN}` env placeholders — no template render needed. ## Network aliases (internal resolution) ```yaml caddy: networks: mcnet: aliases: - "auth.${BASE_DOMAIN}" ``` Lets `minecraft` reach `http://auth.ulicraft.net/authlib-injector` from inside the stack. ## conf.d snippets The Caddyfile imports per-vhost snippets from `caddy/conf.d/`: - `00-core.caddy` — `auth.` → drasl. - `10-static.caddy` — apex landing (`/srv/www`) + `/launcher/*` (`/srv/launcher`). - `30-distribution.caddy` — `distribution.` → `/srv/distribution` (static, from `DISTRIBUTION_WEB_ROOT`, another repo). - `40-avatar.caddy` — `avatar.` → `nmsr:8080` (skin/avatar renderer). - `50-status.caddy` — `status.` → `uptime-kuma:3001` (status page). All vhosts are plain `http://…`; TLS is nginx's job. Mounts: `./www:/srv/www:ro`, `./launcher:/srv/launcher:ro`, `${DISTRIBUTION_WEB_ROOT}:/srv/distribution:ro`. ## Notes / risks - drasl behind a proxy: with matching `BaseURL` and nginx terminating TLS it is fine; nginx passes the original Host through to caddy → drasl. - `/launcher/` is a sibling mount (`/srv/launcher`), not nested under the read-only `/srv/www`; `handle_path` strips the prefix. ## Tasks - [ ] `caddy` service in `docker-compose.yml`, published `127.0.0.1:${CADDY_HTTP_PORT}:80` - [ ] Pass `BASE_DOMAIN` + `DISTRIBUTION_WEB_ROOT` into caddy env - [ ] Caddyfile imports `conf.d/*.caddy` - [ ] Network alias for `auth.` subdomain - [ ] Mount `./www`, `./launcher`, `${DISTRIBUTION_WEB_ROOT}` - [ ] Confirm reverse_proxy to drasl works (auth web UI loads, Yggdrasil API responds) - [ ] Verify internal alias resolution from `minecraft` container (curl authlib-injector) - [ ] Verify nmsr + uptime-kuma proxied (`avatar.` renders, `status.` loads)