Admin overview
The admin UI is a Blazor Server app mounted on the same process as the API, gated by the AdminPolicy authorization policy. It runs at /admin on the server origin and is intended for operators of a Pia Server instance — not end users.
Who counts as an administrator comes from the Admin:Emails configuration key (ADMIN_EMAILS in the Compose files): every address listed there is granted the admin role at startup, and re-checked on each sign-in, so adding an address needs no restart. Further admins are promoted from an account’s own page, reached from Accounts — subject to the licence’s admin seat count (see Licensing).
Holding the admin role only opens the console door — which areas an admin sees once inside is a separate grant, made through a named permission bundle. See Admin access for how bundles work, the built-in Owner bundle, and the three areas — Certificates, Settings, License — that carry a high-trust warning when granted.
A brand-new install starts in setup mode instead, which is about the licence rather than about people — see /admin/setup below.
| Route | Purpose |
|---|---|
/admin/setup |
Licence activation for an unlicensed install — setup token + .lic file. Unreachable once the licence is valid |
/admin |
Landing dispatcher — redirects to the first area you can view, or shows a no-areas notice if none is granted |
/admin/accounts |
Accounts — search users, change roles, disable/re-enable |
/admin/access |
Admin access — Owner-only: create permission bundles and assign them to admins |
/admin/devices |
Registered E2EE devices, their status, and the sync cursors behind them |
/admin/groups |
Groups and group-scoped policy / AI provider overrides |
/admin/limits |
Runtime policies — rate limits, quotas, identity policy, AI payload limits — same page as Settings, Limits tab |
/admin/audit |
Filterable audit log of admin and security-relevant events (Events tab) |
/admin/anomalies |
Login anomalies (impossible-travel, brute-force patterns) needing review — same page as Audit, Anomalies tab |
/admin/guardrail-decisions |
Guardrail firings against chat requests — same page as Audit, Guardrails tab |
/admin/license |
Edition, expiry, seat counts, feature flags from the active license (Status tab), plus recent licence history — issue, refresh, expiry (Events tab) |
/admin/ai-providers |
The server-wide AI provider catalog — entries from Ai:Providers in configuration plus database rows added here, tested and managed together, plus server-wide mode-provider assignment |
/admin/settings |
Configuration mirror, runtime policies, and the destructive data actions (Overview/Authentication/Limits/Data tabs) |
/admin/certificates |
Plugin-signing certificates served to clients — its own page |
/admin/guardrails |
Guard-type catalog (policy prompts, severity labels) — its own page |
/admin/token-usage |
AI token usage — charts and breakdowns per user, per model and per group, including a KB column counting knowledge-base searches per request |
/admin/items |
Sync inventory across users (templates, personas, providers, sessions, memory, todos, jobs, chats) |
/admin/plugins |
Installed and available plugins |
/admin/knowledge-bases |
Vector-backed knowledge-base catalog — create a KB, then enable it per group on the group’s edit page |
/admin/connectors |
Pia Mesh pods on the tool plane — transport, identity, presence, group grants |
/admin/operators |
Pia Mesh operators on the task plane — runtime status and group grants |
/admin/managed-personas |
Admin-authored personas published read-only to a group, with optional knowledge-base and connector bindings |
/admin/client-policies |
Client policies — desktop settings preset or pinned, written once and published from any group |
Detail and editor routes hang off those list pages — /admin/users/{id}, /admin/items/{userId}, /admin/token-usage/{userId}, and the create/edit routes for groups, connectors, operators, knowledge bases, managed personas and client policies. Each is reachable from its list; none has to be typed.
Activating a new install
Section titled “Activating a new install”Until the server holds a valid licence it runs in setup mode: every admin route redirects to
/admin/setup, a page titled Activate Pia that asks for two things.
-
Setup token — printed in the startup log of an unlicensed server, under a banner reading
PIA SETUP MODE — server requires license activation, and written to./.setup-tokenin the app directory (override withSetup:TokenPath). If you missed the log line, read either:Terminal window docker logs pia-server | grep -A2 'PIA SETUP MODE'docker exec pia-server cat /app/.setup-tokenThe token is generated only while the licence is invalid; once activation succeeds the server invalidates it and deletes the file. A restart of a licensed server does not mint a new one.
-
License file — drop in or paste the contents of your signed
.lic. See Licensing for how to obtain one.
Setup mode is about the licence, not about accounts. It does not create an administrator and does not
promote whoever opens it — that comes from Admin:Emails. After activation you are redirected to
/admin/login, and you still need an account whose address is in ADMIN_EMAILS to get in.
Refreshing a table
Section titled “Refreshing a table”Tables in the admin UI carry a Refresh button. Usually it sits in the table’s own header; on the two tabbed pages whose tables share one data load — a user’s synced items, and the Token Usage breakdowns — it sits above the tab strip instead and refreshes whichever tab is open. Either way it re-reads the data in place, so the open tab, search term, sort order and scroll position all survive; a browser reload discards them. Storage Areas on Settings → Data is the exception: that list is fixed in the page, so there is nothing to re-read and no button.
Where the data changes without an admin doing anything, the button is followed by an interval picker (OFF / 30S / 5M): accounts, devices and sync cursors, the audit log, login anomalies, licence events, guardrail decisions, token usage, a user’s synced items, and knowledge-base documents being ingested. It starts at OFF; choose an interval and the table re-reads itself until you switch it off or leave the page. If a re-read fails, the interval switches off and the header says so, leaving the figures from the last successful read on screen.
The remaining tables — groups, plugins, the knowledge-base catalog, certificates and guard types — offer the button on its own, because they only change when you change them.