Capture what this session learned the hard way, in plan/03-drasl.md and CLAUDE.md: - Correct admin key is DefaultAdmins (not DefaultAdminUsernames); wrong/unknown keys are silently ignored by drasl (logged as "unknown config option"). - CORSAllowOrigins must be top-level, before any [Section], or it's ignored. - First-admin bootstrap under invite mode is a chicken-egg → temp-flip RequireInvite=false, register, revert. - NMSR needs the auth. host-gateway pin + https mojank endpoints or avatars render the default skin (cross-ref plan/19-routes.md). - Fix the stale example config and mark the admin-bootstrap task done. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.9 KiB
3.9 KiB
Drasl — self-hosted auth (Yggdrasil + skins)
Summary
Self-hosted, Yggdrasil-compatible auth + skin server. Drop-in Mojang replacement
via authlib-injector. Image: unmojang/drasl:latest. Reached only through Caddy
at auth.ulicraft.net; no host port.
OIDC/Keycloak is OUT for now — drasl runs in password-login mode
(AllowPasswordLogin = true). Admin + guests register with a username/password on
the drasl web UI. Re-introducing Keycloak OIDC later is a future task.
Config is TOML only (no env var support). So config.toml is rendered from
config.toml.tmpl by tooling/render-config.sh to inject BASE_DOMAIN.
config.toml.tmpl (key fields)
BaseURL = "https://auth.${BASE_DOMAIN}" # public scheme is HTTPS (nginx TLS)
Domain = "auth.${BASE_DOMAIN}"
ListenAddress = "0.0.0.0:25585" # internal; Caddy proxies
DefaultAdmins = ["admin"] # NOT DefaultAdminUsernames (see gotchas)
AllowPasswordLogin = true
# Top-level — NOT under any [Section] (see gotchas).
CORSAllowOrigins = ["https://${BASE_DOMAIN}"]
[ApplicationOwner]
# ...
# OIDC block intentionally omitted for now (no Keycloak).
# [[RegistrationOIDC]] ← future
Critical gotchas (carry-over)
- 1.21+ secure profile: drasl
SignPublicKeys = falseMUST pair with serverENFORCE_SECURE_PROFILE=FALSE. Linked — both or neither. - authlib endpoint =
BaseURL+/authlib-injector→http://auth.ulicraft.net/authlib-injector. Must match on server and client. Network alias makes this identical inside/outside the stack. Domainaffects skins — if wrong, authlib clients may not see skins.- Config keys are validated loosely — wrong keys are silently ignored (drasl
logs
Warning: unknown config option <key>and moves on). Two that bit us:- Admin list key is
DefaultAdmins(top-level), NOTDefaultAdminUsernames(that key never existed → no admin → admin-only routes likeGET /playersreturn 403). CORSAllowOriginsmust be top-level, before any[Section]. Placed after a table header it parses as<table>.CORSAllowOrigins, is ignored, and the API serves no CORS headers → landing register/account browser calls blocked.RateLimit.Burstis valid in drasl master but warns onunmojang/drasl:latest(image lags) — harmless.
- Admin list key is
- First-admin bootstrap with invite mode on is a chicken-egg.
DefaultAdminsonly promotes the account at startup reconciliation, andPOST /drasl/api/v2/usersis invite-gated (admins do NOT bypass the register endpoint). To create the first admin: temporarily setRequireInvite = falsein the rendered config,docker compose restart drasl,POST /usersto registeradmin, then revert + restart (always trap-revert). API recap:POST /login {username,password}→{apiToken}; admin-onlyGET /playerswithAuthorization: Bearer <token>. - NMSR avatars need https + a host-gateway pin (see
plan/19-routes.md). Drasl's profile embeds https skin URLs (BaseURL is https). NMSR reaches those viaextra_hosts: auth.${BASE_DOMAIN}:host-gateway(host nginx :443, real LE cert) with https mojank endpoints. Without it the skin fetch Connect-fails to caddy:443 and every avatar renders the DEFAULT skin.
Tasks
- Create
drasl/config/config.toml.tmpl(password-login, no OIDC block) - Set
BaseURL/Domaintoauth.${BASE_DOMAIN},ListenAddress 0.0.0.0:25585 - Set
SignPublicKeys = false - Wire
render-config.sh→drasl/config/config.toml(gitignored) - Remove drasl host port from compose (internal only)
- Update compose: drasl on
mcnet, no25585:25585publish - Bootstrap admin account (
admin, done 2026-06-10 via invite-flip; creds in cochi.envfor the mc-status roster). Create guest accounts as needed. - Verify authlib endpoint responds through Caddy
- Future: re-add
[[RegistrationOIDC]]Keycloak block + secret file