# panel-api HTTP API wrapper around panelctl with a web UI. Default bind: `127.0.0.1:9911` ## Endpoints ### Health & UI | Method | Path | Description | |--------|------|-------------| | GET | `/` | Web UI (served from `frontend/index.html`) | | GET | `/health` | Health check | ### Apps — Read | Method | Path | Description | |--------|------|-------------| | GET | `/apps` | List all apps | | GET | `/apps/` | Show single app manifest | | GET | `/apps//routes` | Get parsed route entries | | GET | `/apps//status` | Container status (running/stopped) | | GET | `/apps//compose` | Read compose.yaml content | | GET | `/apps//logs?tail=N` | Fetch last N log lines (default 100) | | GET | `/apps//backups` | List available backups | | GET | `/apps//backups/` | Download backup zip | ### Apps — Write | Method | Path | Description | |--------|------|-------------| | POST | `/apps/init` | Create a new app | | POST | `/apps//routes` | Update routes (hot — Caddy reloads automatically) | | POST | `/apps//deploy` | Deploy (compose up + caddy reload) | | POST | `/apps//restart` | Restart (compose down + up) | | POST | `/apps//stop` | Stop (compose down) | | POST | `/apps//render-route` | Re-render Caddy route | | POST | `/apps//compose` | Save compose.yaml content | | POST | `/apps//validate-compose` | Validate compose file | | POST | `/apps//backup` | Create volume backup (zip) | | POST | `/apps//restore` | Restore from backup | | POST | `/apps//remove` | Remove app | ## Example payloads ### Create app (single route) ```json { "name": "whoami", "routes": [ {"domain": "whoami.srazka.com", "upstream": "127.0.0.1:18080"} ], "auth": true } ``` ### Create app (multiple routes, different ports) ```json { "name": "myapp", "routes": [ {"domain": "app.srazka.com", "upstream": "127.0.0.1:18080"}, {"domain": "api.app.srazka.com", "upstream": "127.0.0.1:18081"} ], "auth": true } ``` ### Create app (multiple routes, different ports, with paths) ```json { "name": "pocketbase", "routes": [ {"domain": "pb.srazka.com", "upstream": "127.0.0.1:8090", "path": "/_/*"} ], "auth": true } ``` The `path` field is optional. When present, it generates a Caddy `reverse_proxy /_/* 127.0.0.1:8090` rule, letting you route requests to a specific path prefix within a domain. ### Create app (wildcard domain) ```json { "name": "wildcard", "routes": [ {"domain": "*.srazka.com", "upstream": "127.0.0.1:18082"} ], "auth": false } ``` Note: Wildcard domains require DNS challenge configuration in Caddy. ### Update routes (hot) ```json { "routes": [ {"domain": "app.srazka.com", "upstream": "127.0.0.1:18080"}, {"domain": "api.srazka.com", "upstream": "127.0.0.1:18081"}, {"domain": "pb.srazka.com", "upstream": "127.0.0.1:8090", "path": "/_/*"} ] } ``` The optional `path` field generates a Caddy `reverse_proxy ` rule for sub-path routing. Caddy reloads automatically via the systemd path watcher. Containers stay running. ### Save compose ```json { "content": "services:\n app:\n image: nginx:latest\n ports:\n - '127.0.0.1:18080:80'\n" } ``` ### Remove and keep volumes ```json { "keepVolumes": true } ``` ### Restore from backup ```json { "file": "whoami-20260101-120000.zip" } ``` ## Routes response ```json { "ok": true, "name": "myapp", "routes": [ {"domain": "app.srazka.com", "upstream": "127.0.0.1:18080"}, {"domain": "api.srazka.com", "upstream": "127.0.0.1:18081", "path": "/api/*"} ] } ``` The `path` field is only present when a route has a path configured. ## Response format All JSON responses include an `ok` boolean: ```json { "ok": true, "apps": [...] } ``` Error responses: ```json { "ok": false, "error": "description", "stderr": "panelctl error output" } ``` ## Status response ```json { "ok": true, "name": "whoami", "running": true, "containers": [ { "name": "whoami-app-1", "state": "running", "image": "docker.io/traefik/whoami:latest" } ] } ``` ## Local test ```bash curl -s http://127.0.0.1:9911/health | jq . curl -s http://127.0.0.1:9911/apps | jq . curl -s http://127.0.0.1:9911/apps/whoami/status | jq . curl -s http://127.0.0.1:9911/apps/whoami/logs?tail=50 | jq . curl -s http://127.0.0.1:9911/apps/whoami/backups | jq . ```