a control panel for my server
at main 117 lines 3.6 kB view raw view rendered
1# Control 2 3![screenshot](https://hc-cdn.hel1.your-objectstorage.com/s/v3/f566255f04dab183_image.png) 4 5This servers as the source of truth for whether stuff is enabled or not. 6 7The canonical repo for this is hosted on tangled over at [`dunkirk.sh/con trol`](https://tangled.org/@dunkirk.sh/control) 8 9## Quick Start 10 11```bash 12bun install 13bun run dev 14``` 15 16## Configuration 17 18### Environment Variables 19 20```bash 21# Server 22PORT=3010 23ORIGIN=http://localhost:3010 # or https://control.dunkirk.sh in production 24NODE_ENV=development # set to "production" for prod 25 26# OAuth (Indiko) 27INDIKO_URL=https://indiko.dunkirk.sh 28CLIENT_ID=https://control.dunkirk.sh/ # Must match Indiko client registration 29CLIENT_SECRET=<from-indiko-admin> # Required for role-based access 30 31# Session 32SESSION_SECRET=<random-32-bytes> 33 34# Flags directory 35FLAGS_DIR=/var/lib/caddy/flags 36 37# Optional: restrict to specific role 38REQUIRED_ROLE=admin 39``` 40 41The `ORIGIN` is used to derive: 42 43- `CLIENT_ID`: `${ORIGIN}/` (if not set explicitly) 44- `REDIRECT_URI`: `${ORIGIN}/auth/callback` 45 46### Indiko Client Setup 47 48To use role-based access control, pre-register Control Panel as a client in Indiko: 49 501. Create a new client in Indiko admin 512. Set client ID to `https://control.dunkirk.sh/` (must match `CLIENT_ID` env) 523. Add `admin` to available roles 534. Copy the client secret to `CLIENT_SECRET` 545. Assign `admin` role to users who should access the control panel 55 56Control Panel publishes OAuth client metadata at `/client-metadata.json` for Indiko auto-discovery. 57 58### Flags Configuration 59 60Edit `flags.json` to define services and their flags: 61 62```json 63{ 64 "services": { 65 "map.dunkirk.sh": { 66 "name": "Map", 67 "flags": { 68 "block-map-sse": { 69 "name": "Block SSE Endpoint", 70 "description": "Disable /sse Server-Sent Events" 71 } 72 } 73 } 74 } 75} 76``` 77 78Each flag creates a marker file at `${FLAGS_DIR}/${flag-id}` when enabled. 79 80### Caddy Integration 81 82Configure Caddy to check for marker files: 83 84``` 85@sse_blocked { 86 path /sse 87 file /var/lib/caddy/flags/block-map-sse 88} 89respond @sse_blocked "SSE temporarily disabled" 503 90``` 91 92## API 93 94| Endpoint | Method | Description | 95| ----------------------- | ------ | ------------------------------------ | 96| `/` | GET | Dashboard UI | 97| `/auth/login` | GET | Start OAuth flow | 98| `/auth/callback` | GET | OAuth callback | 99| `/auth/logout` | POST | Clear session | 100| `/client-metadata.json` | GET | OAuth client metadata for Indiko | 101| `/api/session` | GET | Get current user info | 102| `/api/flags` | GET | List all flags | 103| `/api/flags/:name` | GET | Get flag status | 104| `/api/flags/:name` | PUT | Set flag (`{ enabled: true/false }`) | 105| `/api/flags/:name` | DELETE | Disable flag | 106 107<p align="center"> 108 <img src="https://raw.githubusercontent.com/taciturnaxolotl/carriage/main/.github/images/line-break.svg" /> 109</p> 110 111<p align="center"> 112 <i><code>&copy 2025-present <a href="https://dunkirk.sh">Kieran Klukas</a></code></i> 113</p> 114 115<p align="center"> 116 <a href="https://tangled.org/dunkirk.sh/control/blob/main/LICENSE.md"><img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=O'Saasy&logoColor=d9e0ee&colorA=363a4f&colorB=b7bdf8"/></a> 117</p>