# 19 — HTTP route reference (nmsr, landing, auth) > Quick map of the public + internal HTTP routes. caddy (`caddy/conf.d/*.caddy`) > is the internal router; the host nginx terminates TLS and forwards each vhost > to it by Host header. All `${BASE_DOMAIN}` = `ulicraft.net` in prod. ## Vhost → service (caddy) | Vhost | caddy file | Upstream | |-------|-----------|----------| | `${BASE_DOMAIN}` (apex) | `10-static.caddy` | static `/srv/www` + `/srv/launcher` + mc-status | | `auth.${BASE_DOMAIN}` | `00-core.caddy` | `drasl:25585` | | `avatar.${BASE_DOMAIN}` | `40-avatar.caddy` | `nmsr:8080` | | `status.${BASE_DOMAIN}` | `50-status.caddy` | `uptime-kuma:3001` | | `distribution.${BASE_DOMAIN}` | `30-distribution.caddy` | static `/srv/distribution` (other repo) | --- ## NMSR — `avatar.${BASE_DOMAIN}` (skin/avatar renderer) `reverse_proxy nmsr:8080`. Stateless renderer; pulls profiles+skins from Drasl over mcnet (no public round-trip). - `GET /{mode}/{uuid}?size=N` — render an avatar PNG. - `mode` = any NMSR render mode (`headiso` is the configured default via `AVATAR_MODE`; others incl. `head`, `face`, `fullbody`, `fullbodyiso`). - `uuid` = Drasl player UUID; `size` = px. - Landing usage: `${avatarUrl}/${avatarMode}/?size=64|96`. - **No per-request refresh.** A `?skin=` override is **ignored** by this build (tested). Skin changes propagate via the resolve cache only. - Caching (`nmsr/config.toml`): `resolve_cache_duration = 60s` (uuid→profile, bounds stale-avatar window), `texture_cache_duration = 48h` (safe — Drasl skin URLs are content-hashed, new skin = new URL). Instant global flush = restart nmsr. See `plan/03-drasl.md` for the Drasl-backed mojank wiring. --- ## Landing — `${BASE_DOMAIN}` (apex) `10-static.caddy`. Three handlers: - `handle_path /launcher/*` → `/srv/launcher` (file browse) — launcher downloads. - `handle /api/mcstatus/*` → `uri strip_prefix /api/mcstatus` → `mc-status:8080`: - `/api/mcstatus/v2/status/java/` → internal `/v2/status/java/` — live server status JSON (mcstatus.io-compatible, `CORS: *`, `` ignored — it only pings `MC_STATUS_TARGET`). Landing `statusApi`. - `/api/mcstatus/players` → internal `/players` — registered-players roster, sanitized `[{uuid,name}]`, ~60s cache (mc-status admin-logs-in to Drasl `GET /players`). Landing `rosterApi`. - `/healthz` — mc-status liveness (internal). - `handle {}` → `/srv/www` static (Astro output). Pages: `/`, `/es`, `/eu` (index), `/{lang}/register`, `/{lang}/account`, `/{lang}/fjord`. Browser → Drasl **directly** (CORS-scoped to apex via Drasl `CORSAllowOrigins`), base `https://auth.${BASE_DOMAIN}/drasl/api/v2` (`site.draslApiUrl`): - `register.astro`: `POST /users` (register), `POST /login`, `PATCH /players/{uuid}` (set initial skin). - `account.astro`: `POST /login`, `PATCH /players/{uuid}` with `{skinBase64,skinModel}` (upload) or `{deleteSkin:true}` (reset). --- ## Auth / Drasl — `auth.${BASE_DOMAIN}` `reverse_proxy drasl:25585`. One service exposes three surfaces: - **Web UI:** `/` (login / register / profile pages), `/web/texture/skin/.png`, `/web/texture/cape/.png`. - **Yggdrasil / authlib-injector:** `/authlib-injector` (API root — server JVM agent + clients point here), `/session/minecraft/...`, mojang-compat `/users/profiles/minecraft/{name}` and `/session/minecraft/profile/{uuid}` (also what NMSR calls internally). - **Drasl REST API v2** (`/drasl/api/v2`): - `POST /login` `{username,password}` → `{apiToken}` - `POST /users` `{username,password[,inviteCode]}` — register (invite-gated when `RequireInvite=true`; admins from `DefaultAdmins` are promoted at startup, see `plan/03-drasl.md`) - `GET /players` — **admin only**, full roster - `PATCH /players/{uuid}` — skin CRUD (own player, or admin) - `POST /invites` — admin, mint invite codes --- ## Internal (service → service, over mcnet) - `minecraft` → `-javaagent authlib-injector=http://auth.${BASE_DOMAIN}/authlib-injector` (caddy mcnet alias → drasl). - `nmsr` → `http://auth.${BASE_DOMAIN}` (mojang-compat session/textures/api). - `mc-status` → `http://drasl:25585/drasl/api/v2` (`DRASL_API_URL`) for the roster; pings `MC_STATUS_TARGET` for live status. - `mc-backup` → RCON `minecraft:25575`.