a control panel for my server
Control#
This servers as the source of truth for whether stuff is enabled or not.
The canonical repo for this is hosted on tangled over at dunkirk.sh/con trol
Quick Start#
bun install
bun run dev
Configuration#
Environment Variables#
# Server
PORT=3010
ORIGIN=http://localhost:3010 # or https://control.dunkirk.sh in production
NODE_ENV=development # set to "production" for prod
# OAuth (Indiko)
INDIKO_URL=https://indiko.dunkirk.sh
CLIENT_ID=https://control.dunkirk.sh/ # Must match Indiko client registration
CLIENT_SECRET=<from-indiko-admin> # Required for role-based access
# Session
SESSION_SECRET=<random-32-bytes>
# Flags directory
FLAGS_DIR=/var/lib/caddy/flags
# Optional: restrict to specific role
REQUIRED_ROLE=admin
The ORIGIN is used to derive:
CLIENT_ID:${ORIGIN}/(if not set explicitly)REDIRECT_URI:${ORIGIN}/auth/callback
Indiko Client Setup#
To use role-based access control, pre-register Control Panel as a client in Indiko:
- Create a new client in Indiko admin
- Set client ID to
https://control.dunkirk.sh/(must matchCLIENT_IDenv) - Add
adminto available roles - Copy the client secret to
CLIENT_SECRET - Assign
adminrole to users who should access the control panel
Control Panel publishes OAuth client metadata at /client-metadata.json for Indiko auto-discovery.
Flags Configuration#
Edit flags.json to define services and their flags:
{
"services": {
"map.dunkirk.sh": {
"name": "Map",
"flags": {
"block-map-sse": {
"name": "Block SSE Endpoint",
"description": "Disable /sse Server-Sent Events"
}
}
}
}
}
Each flag creates a marker file at ${FLAGS_DIR}/${flag-id} when enabled.
Caddy Integration#
Configure Caddy to check for marker files:
@sse_blocked {
path /sse
file /var/lib/caddy/flags/block-map-sse
}
respond @sse_blocked "SSE temporarily disabled" 503
API#
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Dashboard UI |
/auth/login |
GET | Start OAuth flow |
/auth/callback |
GET | OAuth callback |
/auth/logout |
POST | Clear session |
/client-metadata.json |
GET | OAuth client metadata for Indiko |
/api/session |
GET | Get current user info |
/api/flags |
GET | List all flags |
/api/flags/:name |
GET | Get flag status |
/api/flags/:name |
PUT | Set flag ({ enabled: true/false }) |
/api/flags/:name |
DELETE | Disable flag |
© 2025-present Kieran Klukas