# Warp admin panel The operator's web UI for a Warp homeserver: dashboard, users, rooms, federation, registration and tokens, server notices, application services and the audit log. It is the frontend of the admin API ([docs/admin-api.md](../../docs/admin-api.md)). The panel is **optional and separate from the homeserver**. It ships as its own small binary, `warp-admin`, with the built Vue app embedded. A Warp server runs the same whether or not you install it. ``` browser ──► warp-admin :8009 ──► warp :8008 serves the panel /_matrix/client/v3/login, logout, account/whoami proxies 5 paths /_matrix/client/versions /_warp/admin/v1/* ``` warp-admin proxies only what the panel uses and answers `404` for anything else, so it is not a second way into the homeserver. Because the browser only talks to warp-admin, the panel is same-origin (no CORS), the homeserver URL is runtime configuration rather than baked into the build, and `/_warp/admin` can stay off your public listener: only warp-admin has to reach it. ## Signing in With a normal account that has the admin flag. Make the first one on the server: ```bash warp create-account --username root --admin ``` The panel logs in like any Matrix client and uses the access token for the admin API. The token is kept in `sessionStorage` (gone with the tab) unless you tick "Stay signed in on this browser". Signing out logs the session out on the homeserver. ## Run it ### With Docker Compose ```bash cd deploy/compose docker compose --profile admin up -d ``` The panel is on . Leave out `--profile admin` and it isn't installed. ### As a container ```bash docker build -t warp-admin -f apps/admin/Dockerfile . docker run -p 8009:8009 -e WARP_ADMIN_HOMESERVER=http://warp:8008 warp-admin ``` ### As a binary ```bash make admin ./bin/warp-admin -homeserver http://localhost:8008 ``` | Flag | Environment | Default | |---|---|---| | `-listen` | `WARP_ADMIN_LISTEN` | `:8009` | | `-homeserver` | `WARP_ADMIN_HOMESERVER` | `http://localhost:8008` | | `-log-format` | `WARP_ADMIN_LOG_FORMAT` | `text` (or `json`) | `/healthz` answers `ok` for container health checks. ## Deploying - Put warp-admin behind your TLS proxy, ideally on a hostname or network only admins can reach. It sends a strict Content-Security-Policy, `X-Frame-Options: DENY` and `Referrer-Policy: no-referrer`. - warp-admin adds `X-Forwarded-For`. The homeserver uses it for rate limits and a session's last-seen IP only with `client_api.trust_x_forwarded_for` on; without it, admin logins count against warp-admin's own address. Turn it on only when every client reaches the homeserver through proxies you control. ## Develop ```bash pnpm install pnpm admin:dev # http://localhost:5174, proxied to localhost:8008 ``` `WARP_ADMIN_HOMESERVER` points the dev server at another homeserver. Vite proxies the same paths warp-admin does, so the app code is the same in both. | Command | What | |---|---| | `make admin-web` | build the frontend into `internal/panel/build/dist` | | `make admin` | build the frontend, then `bin/warp-admin` with it embedded | | `make admin-test` | typecheck the frontend, vet and test the Go host | | `make admin-docker` | build the container image | A `warp-admin` compiled before the frontend is built still runs. It serves a page saying the panel is missing. ## Layout | Path | What | |---|---| | `src/api/` | typed client for the admin API and the login endpoints | | `src/stores/` | the admin's session, toasts (Pinia) | | `src/views/` | one view per page | | `src/components/` | panel-specific pieces: page header, pager, confirm dialog | | `cmd/warp-admin/` | the binary | | `internal/host/` | static serving and the allow-listed proxy | | `internal/panel/` | the embedded build | The design system (tokens, fonts, icons, base components) comes from [`@warp/ui`](../ui/README.md).