CLI Proxy API Management Center with Dockerized Usage Service
50K+
Maintenance status: CPA-Manager is now in maintenance mode. Future work is limited to security maintenance and bug fixes. For new deployments, feature upgrades, and long-term use, migrate to CPA Manager Plus. See the migration guide when upgrading from this project.
A single-file Web UI for CLI Proxy API (CPA) plus an optional Usage Service for persistent usage analytics.
Since v6.10.0, CPA no longer includes built-in usage statistics. This project now supports usage analytics through a long-running Usage Service that consumes the CPA usage queue, persists request events to SQLite, and exposes panel-compatible usage APIs.

/v0/management)amd64 and arm64 packages for Windows, macOS, and Linux with the panel embedded/management.html, then configure a separately deployed Usage Service inside the panel| Mode | Entry URL | What the user configures | Best for |
|---|---|---|---|
| Full Docker mode | http://<host>:18317/management.html | First setup: CPA URL + Management Key; later login: Management Key only | New deployments, one entry point, least browser/CORS complexity |
| CPA panel mode | http://<cpa-host>:8317/management.html | Log in to CPA first, then set the Usage Service URL under Configuration -> CPA-Manager Configuration | Existing CPA automatic panel loading |
| Frontend only | Vite dev server or dist/index.html | CPA URL, optionally Usage Service URL | Development |
Full Docker mode does not bundle CPA itself. CPA still runs as the upstream service; the Docker image provides the Usage Service plus an embedded copy of this management panel.
Request statistics require the CPA usage queue:
/v0/management.usage-statistics-enabled: true, or submit { "value": true } to PUT /usage-statistics-enabled. CPA-Manager enables this automatically when request monitoring is enabled during setup or configuration save.v7.1.0+ is recommended. CPA v6.10.8+ already exposes the HTTP usage queue endpoint /v0/management/usage-queue, which can pass through regular HTTP reverse proxies.auto mode only when subscribe and HTTP queue collection are unavailable. RESP listens on the CPA API port, usually 8317, and cannot pass through a regular HTTP reverse proxy.redis-usage-queue-retention-seconds, default 60 seconds and maximum 3600 seconds. Keep Usage Service running continuously.pollIntervalMs must be less than or equal to the CPA queue retention window converted to milliseconds. Saves are rejected when the collector would poll too slowly and risk expired queue items.Browser
-> Usage Service :18317
-> built-in management.html
-> /v0/management/usage and /v0/management/model-prices from SQLite
-> other /v0/management/* proxied to CPA
-> HTTP/RESP consumer -> CPA API port
-> SQLite /data/usage.sqlite
The login page calls GET /usage-service/info and detects that it is hosted by Usage Service. If the response is not configured yet, it shows the setup wizard: you enter the CPA URL, Management Key, and choose whether to enable request monitoring. When monitoring is enabled, you also set the collector polling interval; Usage Service validates the CPA Management API, enables CPA usage publishing, checks that the poll interval does not exceed the CPA queue retention window, stores CPA-Manager configuration in SQLite, starts the collector with the configured mode (auto by default: subscribe first, HTTP queue second, RESP fallback), and serves the panel from the same origin. When monitoring is disabled, the CPA connection is still saved for Management API proxying, but CPA usage publishing and the collector stay off.
After Usage Service is configured, a new browser opening the same URL uses the normal login form. The user only enters the Management Key; the panel uses the CPA connection saved on the server.
Browser
-> CPA /management.html
-> normal CPA Management API calls stay on CPA
-> usage calls go to configured Usage Service URL
Usage Service
-> HTTP/RESP consumer -> CPA API port
-> SQLite /data/usage.sqlite
Use this when CPA still auto-downloads and serves the panel. This mode is served by CPA, so it does not show the Usage Service-hosted setup wizard. Request monitoring is optional; when Usage Service is not deployed, the panel hides the request monitoring entry and direct visits to the monitoring page show a setup hint. To use request monitoring, log in to CPA first, deploy Usage Service separately, then open Configuration -> CPA-Manager Configuration, enable it, enter the Usage Service URL, and save.
For new deployments, use CPA Manager Plus. The CPA-Manager deployment steps below are kept for users who still need to maintain existing installations.
docker run -d \
--name cpa-manager \
--restart unless-stopped \
-p 18317:18317 \
-v cpa-manager-data:/data \
seakee/cpa-manager:latest
Open:
http://<host>:18317/management.html
On first setup, enter:
http://host.docker.internal:8317 (default suggestion unless the panel was built with VITE_DEFAULT_CPA_BASE_URL)http://cli-proxy-api:8317https://your-cpa.example.comAfter setup, the same entry URL uses the saved CPA connection from Usage Service SQLite. New browsers only need the Management Key on the login page.
The published image supports linux/amd64 and linux/arm64. If your image is published under another Docker Hub namespace, replace seakee/cpa-manager:latest.
GitHub Releases also provide native packages with the panel embedded:
cpa-manager_<version>_linux_amd64.tar.gzcpa-manager_<version>_linux_arm64.tar.gzcpa-manager_<version>_darwin_amd64.tar.gzcpa-manager_<version>_darwin_arm64.tar.gzcpa-manager_<version>_windows_amd64.zipcpa-manager_<version>_windows_arm64.zipmacOS/Linux:
tar -xzf cpa-manager_vX.Y.Z_linux_amd64.tar.gz
cd cpa-manager_vX.Y.Z_linux_amd64
./cpa-manager
The tar archives preserve execute permissions, so no extra chmod +x is normally required after extraction. If macOS blocks the unsigned binary, run xattr -dr com.apple.quarantine . in the extracted directory and start it again.
Windows PowerShell:
Expand-Archive .\cpa-manager_vX.Y.Z_windows_amd64.zip -DestinationPath .
cd .\cpa-manager_vX.Y.Z_windows_amd64
.\cpa-manager.exe
You can double-click cpa-manager.exe on Windows, but PowerShell is recommended because it keeps logs and startup errors visible.
Then open:
http://<host>:18317/management.html
Native packages do not include CPA itself. Run CPA separately, then enter the CPA URL and Management Key during first setup. After setup, the login page only needs the Management Key. Set USAGE_DATA_DIR or USAGE_DB_PATH only when you want to override the default data location.
On first start, if USAGE_DATA_DIR and USAGE_DB_PATH are not set, the native package creates config.json next to the binary and writes SQLite data to data/usage.sqlite in the same directory. The extracted package directory therefore contains both the program and its user data.
services:
cpa-manager:
image: seakee/cpa-manager:latest
restart: unless-stopped
ports:
- "18317:18317"
volumes:
- cpa-manager-data:/data
volumes:
cpa-manager-data:
Start:
docker compose up -d
If CPA runs directly on a Linux host and Usage Service runs in Docker, add a host gateway:
docker run -d \
--name cpa-manager \
--restart unless-stopped \
--add-host=host.docker.internal:host-gateway \
-p 18317:18317 \
-v cpa-manager-data:/data \
seakee/cpa-manager:latest
Then enter http://host.docker.internal:8317 as the CPA URL during first setup.
Start CPA as usual and open:
http://<cpa-host>:8317/management.html
Log in to CPA with the CPA Management Key. This entry is served by CPA and does not use the Usage Service setup wizard.
Deploy Usage Service:
docker run -d \
--name cpa-manager \
--restart unless-stopped \
-p 18317:18317 \
-v cpa-manager-data:/data \
seakee/cpa-manager:latest
In the CPA panel, go to:
Configuration -> CPA-Manager Configuration
Enable it and enter:
http://<usage-service-host>:18317
Save the CPA-Manager configuration.
The panel sends the current CPA URL and Management Key to Usage Service. After that, monitoring reads usage data from Usage Service while other management calls continue to use CPA.
docker compose -f docker-compose.usage.yml up --build
This builds the React panel and embeds it into the Go Usage Service binary.
Most users can configure CPA URL, Management Key, request monitoring enablement, collection mode, and polling interval from Configuration -> CPA-Manager Configuration. CPA-Manager configuration is persisted in SQLite. Environment variables are mainly for first bootstrap and unattended deployments.
The variables below are Usage Service runtime settings. Frontend build-time settings are separate: VITE_DEFAULT_CPA_BASE_URL sets the default CPA URL shown by the Usage Service-hosted first setup wizard. When it is not set, the Docker-hosted panel suggests http://host.docker.internal:8317.
| Variable | Default | Description |
|---|---|---|
CPA_MANAGER_CONFIG | empty | Optional config file path. When empty, native packages use config.json next to the binary |
HTTP_ADDR | 0.0.0.0:18317 | Usage Service HTTP listen address |
USAGE_DB_PATH | Docker: /data/usage.sqlite; native: ./data/usage.sqlite | SQLite database path |
USAGE_DATA_DIR | Docker: /data; native: ./data | Base data directory when USAGE_DB_PATH is not overridden |
CPA_UPSTREAM_URL | empty | Optional CPA base URL for unattended startup |
CPA_MANAGEMENT_KEY | empty | Optional CPA Management Key for unattended startup |
CPA_MANAGEMENT_KEY_FILE | /run/secrets/cpa_management_key | Optional file containing the Management Key |
USAGE_COLLECTOR_MODE | auto | Collection mode: auto probes Redis Pub/Sub subscribe (CPA v7.0.7+), then HTTP usage queue, then RESP polling; subscribe forces Pub/Sub; http forces HTTP; resp forces RESP polling |
USAGE_RESP_QUEUE | usage | RESP key argument; CPA currently ignores it, leave the default unless upstream changes |
USAGE_RESP_POP_SIDE | right | right uses RPOP; left uses LPOP |
USAGE_BATCH_SIZE | 100 | Maximum queue records per pop |
USAGE_POLL_INTERVAL_MS | 500 | Idle polling interval |
USAGE_QUERY_LIMIT | 50000 | Maximum recent events returned through compatible /usage |
USAGE_CORS_ORIGINS | * | Allowed browser origins for CPA panel mode |
USAGE_RESP_TLS_SKIP_VERIFY | false | Skip TLS verification for RESP connection |
PANEL_PATH | empty | Serve a custom management.html instead of the embedded one |
Startup configuration precedence is: environment variables > config.json > program defaults. Relative paths in the config file are resolved from the config file directory. The generated default config is:
{
"httpAddr": "0.0.0.0:18317",
"dataDir": "./data"
}
If CPA_UPSTREAM_URL and CPA_MANAGEMENT_KEY are set, collection starts automatically on boot and the connection is shown as environment-managed in the panel. Otherwise, use the web panel setup flow; the result is saved to SQLite settings.manager_config_v1. The legacy settings.setup value is still written for compatibility and rollback.
usage-statistics-enabled, redis-usage-queue-retention-seconds, proxy, logging, routing, auth files, and related fields still belong to CPA and are managed by /config / /config.yaml.pollIntervalMs, batchSize, queryLimit, and the CPA panel mode Usage Service bootstrap URL are persisted in Usage Service SQLite.config.yaml; enabling request monitoring calls CPA Management API to enable usage publishing, while disabling request monitoring only stops the CPAM collector./data/usage.sqlite./setup, the service can read settings.setup as a fallback and writes the new settings.manager_config_v1 structure on the next save.CPA_UPSTREAM_URL / CPA_MANAGEMENT_KEY, the connection remains environment-managed. To switch to panel persistence, remove those environment variables, restart, and save from the panel./data; mount it to persistent storage.settings table so collection can resume after restart.settings.manager_config_v1; legacy settings.setup is kept as compatibility data./data volume. It contains usage metadata and the saved Management Key.| Endpoint | Purpose |
|---|---|
GET /health | Basic health check |
GET /status | Collector, SQLite, event count, and error status |
GET /usage-service/info | Allows the frontend to detect full Docker mode and read configured for setup vs login flow |
GET /usage-service/config | Reads persistent CPA-Manager configuration and CPA usage publishing status |
PUT /usage-service/config | Saves CPA-Manager configuration and restarts the collector when needed |
POST /setup | Save CPA URL + Management Key and start collection |
GET /v0/management/usage | Compatible usage payload for the panel |
GET /v0/management/usage/export | Export usage events as JSONL |
POST /v0/management/usage/import | Import JSONL usage events or legacy JSON snapshots |
GET /v0/management/model-prices | Read SQLite-backed model pricing |
PUT /v0/management/model-prices | Replace saved model pricing |
POST /v0/management/model-prices/sync | Sync model prices from LiteLLM pricing metadata |
GET /models, GET /v1/models | Proxy model-list requests to CPA after setup |
/v0/management/* | Proxied to CPA except usage endpoints |
After setup, /status, usage, model-pricing, and /v0/management/* proxy endpoints require the same Management Key as a Bearer token.
Usage import accepts two file families: JSONL/NDJSON event files exported by Usage Service, and legacy JSON snapshots produced by older CPA /usage/export. Legacy JSON can be converted only when usage.apis.*.models.*.details[] request details are present. Files that contain only aggregate totals are rejected because request-level monitoring data cannot be reconstructed. Legacy import is a migration/recovery path, not a perfect continuation of newly collected Usage Service data: old files may miss metadata such as api_key_hash, channel, request ID, method/path, latency, cache tokens, or failure reason, so account matching, API Key level analysis, and detail accuracy may be lower. Importing legacy files affects totals, trend charts, and account/key breakdowns; use a test or backup database first when accuracy matters.
Frontend:
npm ci
npm run dev
npm run type-check
npm run lint
npm run build
Open http://localhost:5173, then connect to your CLI Proxy API backend instance.
Usage Service:
cd usage-service
go test ./...
go run ./cmd/cpa-manager
Maintenance policy: CPA-Manager no longer plans feature releases. Except for security maintenance and bug fixes, release and upgrade work should move to CPA Manager Plus.
dist/index.html.vX.Y.Z triggers .github/workflows/release.yml.dist/management.html, native packages, and checksums.txt to GitHub Releases.linux, darwin, and windows on both amd64 and arm64, with the management panel embedded.Dockerfile.usage-service and pushes seakee/cpa-manager.linux/amd64 and linux/arm64.README.md to the Docker Hub overview.VERSION, then git tag, then the package.json fallback.DOCKERHUB_USERNAMEDOCKERHUB_TOKENTip: opening dist/index.html via file:// may be blocked by browser CORS; serving it with npm run preview or another static server is more reliable.
Currently supports four languages:
The UI language is automatically detected from browser settings and can be manually switched from the login page or header language menu.
ES2020--add-host=host.docker.internal:host-gateway.VITE_DEFAULT_CPA_BASE_URL=<your-cpa-url> or enter the correct CPA URL manually./status, and confirm only one consumer is running.unsupported RESP prefix 'H': upgrade CPA to v7.1.0+ and keep the default USAGE_COLLECTOR_MODE=auto so Usage Service can try subscribe and HTTP queue before RESP. On older CPA or forced RESP mode, the CPA URL must be a container/host direct address for port 8317, not a regular HTTP reverse-proxy domain./status for lastConsumedAt, lastInsertedAt, and lastError.USAGE_CORS_ORIGINS to the CPA panel origin or keep the default * for private deployments./data to a Docker volume or host directory.Content type
Image
Digest
sha256:a5ddb3b5d…
Size
14.7 MB
Last updated
3 months ago
docker pull seakee/cpa-manager