Authentication
Always-on, Grafana-style bearer-token auth with three roles. There is no way to disable it, and nothing to configure before first boot.
/ is authenticated. Log in once, then send the returned token as Authorization: Bearer <token> on every subsequent request.First boot seeds admin/admin
On first boot (when the users table is empty) Dokkai seeds an admin / admin user. Setting DOKKAI_ROOT_USER / DOKKAI_ROOT_PASSWORD before that first boot seeds those credentials instead. Setting either on a later boot re-applies it onto the seeded admin — the supported way to reset a lost admin password.
GET /auth/status (public) and GET /auth/me both return default_admin_active: true for as long as any user named admin still verifies against the password admin.Tokens
Tokens are opaque, random 30-day bearer tokens, stored SHA-256-hashed in Postgres — the plaintext is only ever returned once, at login. POST /auth/logout revokes the session for that request; changing your own password revokes every other session for your user but keeps the current one.
Roles
| Role | Can | Cannot |
|---|---|---|
admin | Everything, plus user management and POST /config/llm | — |
user | Chat, ingestion, deletes, all reads | User management, POST /config/llm |
viewer | Read-only GET routes | Chat, ingestion, any delete, user management |
A role that can't perform an action gets 403 with the exact body role '<role>' cannot perform this action.
Public routes
No token required: GET /, GET /docs, GET /redoc, GET /openapi.json, POST /auth/login, GET /auth/status. Every other route requires a valid bearer token; a missing or expired one is 401 with a WWW-Authenticate: Bearer header.
503 at the auth layer before its own handler runs.