64 docs indexed
The obleth Next.js dashboard: what it shows, how to configure it, and how it connects to the Management API.
The control plane is a Next.js dashboard that consumes the obleth Management API exclusively — it never touches Postgres, Redis, or ClickHouse directly. All domain logic, validation, and audit logging is in one place (the Management API), and the dashboard is just a UI.
| Environment | URL |
|---|---|
| Docker Compose (dev) | http://localhost:3002 |
| Kubernetes (Helm default) | http://localhost:3000 (via port-forward) or your Ingress host |
In the Docker Compose stack, the dashboard uses dev-admin-token by default. Change it by setting OBLETH_ADMIN_TOKEN and OBLETH_ADMIN_BASE_URL in the control-plane environment.
in_flight, queued, max_in_flightfast, queued, rejected)PATCH /api/v1/tenants/{id}/weight)PUT /api/v1/tenants/{id}/quota)GET /api/v1/usage/keys/summary.
Keys with no traffic in the window show "Never". For a single key's exact
last-used time across full retention, call
GET /api/v1/keys/{id}/usage.chat, embedding, audio_transcription, audio_speech, or image); the form reveals the cost fields that apply to that modality (cost_per_image, cost_per_character) and shows a type badge on each rowstatic / tuned), and status0.00000008) instead of scientific notation, so they stay readable and editable0 = model opted out)Show benchmark toggleapi_base + api_key flow) and Slurm provisioned (Apptainer image + launch command; no static endpoint). Slurm-provisioned models show a Provisioning tab with replica state, target count, and spec editing. Non-Slurm models never show this tab. See Slurm Provisioning.The Models page has Import and Export buttons for managing routes in bulk — useful for backups, moving a model set between environments, or seeding a fresh deployment.
Export downloads a JSON file (obleth-models-<date>.json) containing every registered route. Server-assigned fields (id, timestamps) and the upstream api_key are intentionally omitted, so the export is safe to share and never leaks secrets.
Import accepts the obleth models template only — a file with a top-level models: list, in either YAML or JSON. Foreign formats (LiteLLM model_list, Kubernetes ConfigMaps) are not accepted. After you pick a file, the dashboard shows a preview that diffs the file against the current registry before anything is written:
model_name and updated in place)N models in file / X new / Y to updateOn import, routes are matched by model_name. Fields omitted from a model entry fall back to existing values on update, or to sane defaults on create. Per-model failures (e.g. a rejected api_base) are collected and shown individually in the result banner rather than aborting the whole import.
Required fields per model: model_name, upstream_model, api_base. Everything else is optional:
# obleth models import template
models:
- model_name: qwen3-235b-a22b-instruct-2507
description: Qwen3 235B A22B instruct
model_type: chat # chat | embedding | audio_transcription | audio_speech | image
upstream_model: asuair/qwen3-235b-a22b-instruct-2507
api_base: https://openai.rc.asu.edu/v1
api_key: sk_1234 # optional; omit to leave unset / unchanged
input_cost_per_token: 0.000000071
output_cost_per_token: 0.0000001
context_window: 262144
admission_weight: 100
max_in_flight: # blank = no cap
supports_function_calling: true
supports_system_messages: true
supports_response_schema: true
supports_tool_choice: true
enabled: true
tags: [general, long-context]
boons: [] # e.g. [vision, structured_output]; gateway capabilities granted to a model that lacks them natively
tool_servers: [] # registered MCP servers whose tools this model may use (gateway tool loop)
# Non-chat routes set model_type and the cost field for their modality:
- model_name: qwen3-embedding-8b
model_type: embedding
upstream_model: Qwen/Qwen3-Embedding-8B
api_base: https://openai.rc.asu.edu/v1
input_cost_per_token: 0.00000001
enabled: true
- model_name: sdxl
model_type: image
upstream_model: stabilityai/stable-diffusion-xl-base-1.0
api_base: https://openai.rc.asu.edu/v1
cost_per_image: 0.02 # billed × n
enabled: true
- model_name: qwen3-tts
model_type: audio_speech
upstream_model: Qwen/Qwen3-TTS
api_base: https://openai.rc.asu.edu/v1
cost_per_character: 0.000015 # billed per input character
enabled: true
Routing tags use the fixed auto-router vocabulary: coding, general, reasoning, math, vision, long-context, fast, creative. Only chat routes participate in auto routing. See Multi-modal Models for the modality fields.
Note: By default, internal cluster
api_basehosts (e.g.*.svc.cluster.local) are allowed — private/LAN addresses are permitted for local-first deployments. Link-local and cloud-metadata targets are always blocked. If you run strict SSRF mode (OBLETH_BLOCK_PRIVATE_NETWORKS=1), add the pod CIDR toOBLETH_ALLOWED_PRIVATE_CIDRS(e.g.10.0.0.0/8); blocked hosts surface as per-model errors in the import result banner.
in_flight, queued, served_tokens, share_scoreA live, per-request view of traffic as it lands in the ClickHouse usage ledger.
Unlike Overview and Reports, which read aggregates, Request Logs returns
individual rows — one per completed request (successes and rejections like 429/403)
with a timestamp, latency, cost, and tenant/key attribution.
success / error), Traced only (show only requests with recorded spans)request_id UUIDColumns shown: Time, Type, Status, Model, Session, Request ID, Cost, Energy (Wh, when energy accounting is enabled), Tokens, TTFT, Duration, Team, Key. Team and key names are resolved from Postgres; the ledger itself stores only UUIDs. The detail view adds the request's energy cost and CO₂.
Request type is derived from the API path (chat, embedding, audio,
image, completion, responses, rerank, moderation, or other).
Session ID groups related requests when the client supplies one. obleth checks, in order:
x-obleth-session-id or x-session-id headersession_id in the JSON bodymetadata.session_id in the JSON bodyuser in the JSON body (OpenAI convention)Values are trimmed and capped at 200 characters. If none are present, the Session column is empty.
Requests that were traced (i.e. the key or tenant had tracing_enabled set)
show a small trace icon in the row. Clicking any row opens the Request Detail
panel, which shows:
auth_resolve →
"Auth", boon:tool_loop:iter:0 → "Iter 0", etc.).To enable tracing, toggle tracing_enabled on the relevant tenant (Tenants page)
or API key (API Keys page). See Per-request span tracing.
The page calls GET /api/v1/usage/logs
via the control-plane BFF (/api/live/usage/logs). Raw rows are retained for the
configured retention window (default 180 days); the permanent usage_daily rollup
behind Reports is unaffected.
Long-range usage analytics backed by the permanent usage_daily rollup, so the
Reports page keeps full history even after the raw ledger has been pruned to its
retention window. It calls GET /api/v1/usage/daily.
cost_usd) and key name by default alongside the token, latency, and energy columns (Energy (kWh), CO₂ (g), Energy cost (USD))usage_daily rollup behind Reports is unaffected| Variable | Purpose |
|---|---|
OBLETH_ADMIN_BASE_URL | Base URL of the Management API (e.g. http://localhost:9180) |
OBLETH_ADMIN_TOKEN | Admin bearer token for all Management API calls |
DASHBOARD_ADMIN_EMAIL | Email for the break-glass admin (sign-in is email-based) |
DASHBOARD_PASSWORD | Break-glass admin password (or DASHBOARD_PASSWORD_HASH) |
DASHBOARD_SESSION_SECRET | Session cookie signing secret (≥32 chars; change in production) |
DATABASE_URL | Postgres URL for the auth tables (same DB as the gateway) |
OIDC_PROVIDERS | Optional JSON array enabling OIDC SSO — see the Dashboard SSO guide |
In the Docker Compose stack, these are configured via deploy/docker/.env.