Authentication & roles
Tsuki Panel has a bootstrap admin password that always works, plus optional Discord OAuth with role-based access.
Roles
| Role | Can |
|---|---|
| admin | Everything: server commands, config, schedules, backups, and the save editor |
| viewer | Read-only: view dashboards, players, map, logs — but no mutating actions |
The UI hides admin-only controls (server controls, config actions, kick/ban, save editor) from viewers, and the API enforces it: every mutating route requires the admin role.
Bootstrap admin password
Always available, so you're never locked out:
AUTH_PASSWORD=your-strong-password # required — compose won't start without it
JWT_SECRET=<long-random-string> # required, min 16 chars — signs the session
COOKIE_NAME=tsuki_session # optional
SESSION_TTL=7d # optional session lifetimeSign in with this password from the login page. The session is an HTTP-only cookie signed with JWT_SECRET.
TIP
Generate a secret with openssl rand -hex 32. Set COOKIE_SECURE=true once you're on HTTPS.
Discord OAuth (optional)
Let people sign in with Discord and grant roles by their Discord rank (role) or user id.
1. Create a Discord app
- Go to https://discord.com/developers/applications → New Application.
- Under OAuth2, add a redirect that matches your
DISCORD_REDIRECT_URIexactly, e.g.https://panel.example.com/api/auth/discord/callback. - Copy the Client ID and Client Secret.
2. Configure the panel
DISCORD_CLIENT_ID=...
DISCORD_CLIENT_SECRET=...
DISCORD_REDIRECT_URI=https://panel.example.com/api/auth/discord/callback
DISCORD_GUILD_ID=987654321098765432 # your Discord server id (required for roles)3. Choose who gets in, and who's admin
By role (recommended):
# Members with an admin ROLE get full access; everyone else allowed = viewer.
DISCORD_ADMIN_ROLE_IDS=111111111111111111
# Optional: ONLY members with one of these roles may sign in at all.
# Leave empty to let any guild member sign in as a viewer.
DISCORD_ALLOWED_ROLE_IDS=222222222222222222By user id (extra / fallback, combined with the above):
DISCORD_ALLOWED_IDS=111111111111111111,222222222222222222
DISCORD_ADMIN_IDS=111111111111111111Fail-closed by design
If neither a guild nor an id allowlist is set, Discord login is refused — so a misconfiguration can never accidentally let the whole internet in. The password admin always still works.
Redirect URI gotcha
A common mistake is a double slash in the redirect (https://panel.example.com//api/...). It must match the Discord app registration character-for-character, and use your https:// domain in production.