Security & Admin¶
API Keys Section¶
API keys control client access to the router's endpoints. Keys can be configured through multiple sources.
Authentication Mode¶
The mode setting controls whether API authentication is required for API endpoints:
| Mode | Behavior |
|---|---|
permissive (default) | Allow requests without API key. Requests with valid API keys are authenticated. |
blocking | Only process requests that pass API key authentication. Unauthenticated requests receive 401. |
Target Endpoints (when mode is blocking): - /v1/chat/completions - /v1/completions - /v1/responses - /v1/images/generations - /v1/images/edits - /v1/images/variations - /v1/models
Note: Admin, Files, and Metrics endpoints have separate authentication mechanisms and are not affected by this setting.
Section Configuration Properties:
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
mode | string | No | permissive | Authentication mode: permissive or blocking |
api_keys | array | No | [] | Inline API key definitions |
api_keys_file | string | No | - | Path to external API keys file |
api_keys:
# Authentication mode: "permissive" (default) or "blocking"
mode: permissive
# Inline API key definitions
api_keys:
- key: "${API_KEY_1}" # Environment variable substitution
id: "key-production-1" # Unique identifier
user_id: "user-admin" # Associated user
organization_id: "org-main" # Associated organization
name: "Production Admin Key" # Human-readable name
scopes: # Permissions
- read
- write
- files
- admin
rate_limit: 1000 # Requests per minute (optional)
enabled: true # Active status
expires_at: "2025-12-31T23:59:59Z" # Optional expiration (ISO 8601)
- key: "${API_KEY_2}"
id: "key-service-1"
user_id: "service-bot"
organization_id: "org-main"
name: "Service Account"
scopes: [read, write, files]
rate_limit: 500
enabled: true
# External key file for better security
api_keys_file: "/etc/continuum-router/api-keys.yaml"
Key Properties:
| Property | Type | Required | Description |
|---|---|---|---|
key | string | Yes | The API key value (supports ${ENV_VAR} substitution) |
id | string | Yes | Unique identifier for admin operations |
user_id | string | Yes | User associated with this key |
organization_id | string | Yes | Organization the user belongs to |
name | string | No | Human-readable name |
description | string | No | Notes about the key |
scopes | array | Yes | Permissions: read, write, files, admin |
rate_limit | integer | No | Maximum requests per minute |
enabled | boolean | No | Active status (default: true) |
expires_at | string | No | ISO 8601 expiration timestamp |
External Key File Format:
# /etc/continuum-router/api-keys.yaml
keys:
- key: "sk-prod-xxxxxxxxxxxxxxxxxxxxx"
id: "key-external-1"
user_id: "external-user"
organization_id: "external-org"
scopes: [read, write, files]
enabled: true
Security Features:
- Key Masking: Full keys are never logged (displayed as
sk-***last4) - Expiration Enforcement: Expired keys are automatically rejected
- Hot Reload: Update keys without server restart
- Audit Logging: All key management operations are logged
- Constant-Time Validation: Prevents timing attacks
- Max Key Limit: 10,000 keys maximum to prevent DoS
Admin API Endpoints (require admin authentication):
| Endpoint | Method | Description |
|---|---|---|
/admin/api-keys | GET | List all keys (masked) |
/admin/api-keys/:id | GET | Get key details |
/admin/api-keys | POST | Create new key |
/admin/api-keys/:id | PUT | Update key properties |
/admin/api-keys/:id | DELETE | Delete key |
/admin/api-keys/:id/rotate | POST | Generate new key value |
/admin/api-keys/:id/enable | POST | Enable key |
/admin/api-keys/:id/disable | POST | Disable key |
WebUI Section¶
The optional webui section controls the embedded browser-based administration interface. The WebUI is compiled into the binary and served as static assets protected by admin authentication.
webui:
enabled: true # Enable or disable the WebUI (default: true)
path_prefix: /webui # URL path prefix (default: /webui)
Configuration Properties:
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable or disable the WebUI |
path_prefix | string | /webui | URL path prefix. Must start with / and must not contain ... |
When webui is omitted, the defaults apply: WebUI is enabled at /webui. To disable the WebUI:
See Embedded WebUI for a full guide to using the browser interface.
Admin Section¶
The admin section configures the Admin REST API, including authentication and statistics collection.
Authentication¶
admin:
auth:
method: bearer_token # Auth method: none, bearer_token, basic, api_key
token: "${ADMIN_TOKEN}" # Token for bearer_token method
See Admin REST API Reference for all authentication options.
Statistics Collection¶
The admin.stats subsection controls request metrics collection and persistence. Stats collection is enabled by default.
admin:
stats:
enabled: true # Enable/disable collection (default: true)
retention_window: 24h # Ring-buffer retention for windowed queries (default: 24h)
token_tracking: true # Parse response bodies for token usage (default: true)
persistence:
enabled: true # Enable stats persistence across restarts (default: true)
path: ./data/stats.json # File path for the snapshot (default: ./data/stats.json)
snapshot_interval: 5m # How often to write periodic snapshots (default: 5m)
max_age: 7d # Discard snapshots older than this on startup (default: 7d)
Configuration Properties:
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable or disable statistics collection |
retention_window | string | 24h | Ring-buffer retention window for windowed queries |
token_tracking | boolean | true | Parse response bodies to extract token usage |
Persistence Properties:
| Property | Type | Default | Description |
|---|---|---|---|
persistence.enabled | boolean | true | Enable stats persistence across restarts |
persistence.path | string | ./data/stats.json | File path for the persistence snapshot |
persistence.snapshot_interval | string | 5m | Interval between periodic snapshots |
persistence.max_age | string | 7d | Maximum age for restoring snapshots on startup |
When persistence is enabled:
- On startup, the router restores counters and ring-buffer records from the snapshot file. Uptime always resets to zero.
- A background task writes snapshots atomically (temp file + rename) at the configured interval.
- On graceful shutdown (SIGTERM/SIGINT), a final snapshot is saved.
- Missing, corrupted, or stale snapshots are handled gracefully — the router starts with fresh counters and logs a warning.
Hot Reload: retention_window and token_tracking support immediate hot-reload. Persistence settings (path, snapshot_interval, max_age) require a restart.
Supported duration formats for retention_window, snapshot_interval, and max_age:
| Format | Example | Meaning |
|---|---|---|
Xs | 30s | 30 seconds |
Xm | 5m | 5 minutes |
Xh | 1h | 1 hour |
Xd | 7d | 7 days |
See Admin REST API Reference — Statistics APIs for the full endpoint documentation.
ACP (Agent Communication Protocol) Section¶
The acp section configures the Agent Communication Protocol subsystem. ACP enables IDE and tool integrations to communicate with the router via JSON-RPC 2.0 over stdio. ACP is disabled by default for backward compatibility.
To use ACP, run the router with --mode stdio.
acp:
enabled: true
transport:
stdio:
enabled: true
agent:
name: "Continuum Router"
version: "1.0.0"
description: "Local LLM inference agent"
capabilities:
load_session: true
image: false
audio: false
embedded_context: false
mcp: true
default_model: "gpt-4o"
system_prompt: "You are a helpful coding assistant."
coding_agent_mode: true
permissions:
default_policy: ask_always
auto_allow:
- read
- search
- think
always_ask:
- edit
- delete
- execute
sessions:
max_concurrent: 10
idle_timeout: "1h"
storage: "memory"
mcp:
max_connections_per_session: 5
allowed_servers: []
server_spawn_timeout: "10s"
Top-Level Options¶
| Property | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable/disable the ACP subsystem |
default_model | string | none | Override model selection for ACP sessions |
system_prompt | string | none | Inject a system prompt into all ACP requests |
coding_agent_mode | bool | false | Enable coding agent system prompt |
Transport Options¶
| Property | Type | Default | Description |
|---|---|---|---|
transport.stdio.enabled | bool | true | Enable stdio transport |
Permission Options¶
| Property | Type | Default | Description |
|---|---|---|---|
permissions.default_policy | enum | ask_always | Default policy: ask_always, allow_read, allow_all |
permissions.auto_allow | list | [read, search, think] | Tool kinds auto-allowed without asking |
permissions.always_ask | list | [edit, delete, execute] | Tool kinds that always require permission |
Session Options¶
| Property | Type | Default | Description |
|---|---|---|---|
sessions.max_concurrent | int | 10 | Maximum concurrent sessions |
sessions.idle_timeout | string | "1h" | Idle timeout before session cleanup |
sessions.storage | string | "memory" | Storage backend: memory or file |
sessions.storage_path | string | none | Path for file-based storage |
MCP Bridge Options¶
| Property | Type | Default | Description |
|---|---|---|---|
mcp.max_connections_per_session | int | 5 | Max MCP connections per session |
mcp.allowed_servers | list | [] | Allowed server IDs (empty = all) |
mcp.server_spawn_timeout | string | "10s" | Timeout for spawning MCP server processes |
See ACP Architecture for protocol details and ACP Usage Guide for practical examples.