export const meta = {
  title: 'Console Configuration',
  description: 'All environment variables for the control node.',
  section: 'Getting Started',
  order: 35,
  slug: 'console-config',
}

# Console Configuration

The console (control node) can be configured through environment variables. Set them in `docker-compose.yml` or your container orchestration tool.

## Environment variables

### Core

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_HASH_KEY` | Yes | | HMAC key for hashing worker secrets and access tokens |
| `CONSOLE_HTTP_ADDR` | No | `:8089` | Dashboard and REST API listen address |
| `CONSOLE_GRPC_ADDR` | No | `:50051` | Worker gRPC listen address |

### Database

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_DB_PATH` | No | `./db/onlyboxes-console.db` | SQLite database file path |
| `CONSOLE_DB_BUSY_TIMEOUT_MS` | No | `5000` | SQLite busy timeout (ms) |
| `CONSOLE_TASK_RETENTION_DAYS` | No | `30` | Retention days for completed task records |

### Initial admin account

These variables are only used during first startup when no admin account exists. They are ignored on subsequent runs.

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_DASHBOARD_USERNAME` | No | | Initial admin username |
| `CONSOLE_DASHBOARD_PASSWORD` | No | | Initial admin password |
| `CONSOLE_INITIAL_ADMIN_API_KEY` | No | | Explicit initial admin API key |

### Account

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_ENABLE_REGISTRATION` | No | `false` | Allow admin to register non-admin accounts |

### Tool management

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_HIDDEN_TOOLS` | No | | Comma-separated **internal capability IDs** to hide from MCP `tools/list` (`echo`, `pythonExec`, `terminalExec`, `computerUse`, `readImage`, `exportFile`). Always use the built-in IDs here — never the renamed value supplied via `CONSOLE_MCP_TOOL_<TOOL>_NAME`. Hidden tools remain callable if the client already knows the tool name. |
| `CONSOLE_MCP_TOKEN_QUERY_PARAM` | No | `token` | Query parameter name for the `/mcp` URL-token fallback used by clients that cannot send custom headers. Bearer headers remain recommended. |

#### Tool description / parameter overrides

These env vars let you rewrite what each tool advertises to the model without recompiling. Unset variables keep the built-in defaults. The tool name segment uses `UPPER_SNAKE_CASE` (e.g. `pythonExec` → `PYTHON_EXEC`), and the parameter segment is the uppercased snake_case JSON key (e.g. `session_id` → `SESSION_ID`).

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_MCP_TOOL_<TOOL>_NAME` | No | built-in | Override the tool's `name` exposed via `tools/list` (the routing key used by `tools/call`). Must match `^[a-zA-Z0-9_-]{1,64}$`; empty / invalid values fall back to the default with a warn log. Overrides that collide with another tool's built-in default name (e.g. setting `ECHO_NAME=pythonExec`) also fall back. After changing this, MCP clients must refresh their cached `tools/list`, otherwise `tools/call` against the old name returns "tool not found". `CONSOLE_HIDDEN_TOOLS` keeps using the internal capability ID (`echo`), not the renamed value. |
| `CONSOLE_MCP_TOOL_<TOOL>_TITLE` | No | built-in | Override the tool's human-readable title in `tools/list` and `annotations.title`. An empty string falls back to the default and logs a warning. |
| `CONSOLE_MCP_TOOL_<TOOL>_DESCRIPTION` | No | built-in | Override the tool's `description`. An empty string falls back to the default and logs a warning. |
| `CONSOLE_MCP_TOOL_<TOOL>_PARAM_<PARAM>_DESCRIPTION` | No | built-in | Override a single parameter's `description` in `inputSchema.properties.<param>`. **Setting this to an empty string hides the parameter from `tools/list`**: the entry is removed from `properties` and `required`, and the schema's `additionalProperties` flips to `true` so MCP / HTTP callers may still transmit the field (the handler still receives it). Every hidden parameter emits a startup `WARN hiding MCP tool parameter ... required=<bool>`; hiding a required parameter means the model cannot construct a valid call. |

Supported `<TOOL>` segments and their `<PARAM>` keys:

| Tool | `<TOOL>` | `<PARAM>` values |
| --- | --- | --- |
| `echo` | `ECHO` | `MESSAGE`, `TIMEOUT_MS` |
| `pythonExec` | `PYTHON_EXEC` | `CODE`, `TIMEOUT_MS` |
| `terminalExec` | `TERMINAL_EXEC` | `COMMAND`, `SESSION_ID`, `CREATE_IF_MISSING`, `LEASE_TTL_SEC`, `TIMEOUT_MS` |
| `computerUse` | `COMPUTER_USE` | `COMMAND`, `TIMEOUT_MS`, `REQUEST_ID` |
| `readImage` | `READ_IMAGE` | `SESSION_ID`, `FILE_PATH`, `TIMEOUT_MS` |
| `exportFile` | `EXPORT_FILE` | `SESSION_ID`, `FILE_PATH`, `TIMEOUT_MS` |

Example:

```bash
# Rename the echo tool to "ping", replace its description, and hide terminalExec's session_id parameter
CONSOLE_MCP_TOOL_ECHO_NAME="ping"
CONSOLE_MCP_TOOL_ECHO_DESCRIPTION="ping-only echo"
CONSOLE_MCP_TOOL_TERMINAL_EXEC_PARAM_SESSION_ID_DESCRIPTION=""
```

### Export file object store

These variables enable the MCP `exportFile` tool. The tool is registered in `tools/list` only after the following environment variables are configured.
- `CONSOLE_EXPORT_FILE_ENDPOINT`
- `CONSOLE_EXPORT_FILE_REGION`
- `CONSOLE_EXPORT_FILE_BUCKET_NAME`
- `CONSOLE_EXPORT_FILE_EXPORT_PREFIX`
- `CONSOLE_EXPORT_FILE_AK`
- `CONSOLE_EXPORT_FILE_SK`

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_EXPORT_FILE_ENDPOINT` | No | | S3-compatible endpoint URL used for presigned upload/download |
| `CONSOLE_EXPORT_FILE_REGION` | No | | Explicit signing region |
| `CONSOLE_EXPORT_FILE_BUCKET_NAME` | No | | Destination bucket name |
| `CONSOLE_EXPORT_FILE_EXPORT_PREFIX` | No | | Object key prefix prepended to every export |
| `CONSOLE_EXPORT_FILE_AK` | No | | Access key used for presigning |
| `CONSOLE_EXPORT_FILE_SK` | No | | Secret key used for presigning |
| `CONSOLE_EXPORT_FILE_UPLOAD_PRESIGN_TTL_SEC` | No | `900` | Upload presign TTL in seconds |
| `CONSOLE_EXPORT_FILE_DOWNLOAD_PRESIGN_TTL_SEC` | No | `3600` | Download presign TTL in seconds |
| `CONSOLE_EXPORT_RETURN_SCHEMA` | No | `ALL` | Controls which fields `exportFile` returns: `ALL` (`signed_url` + `object_key` + `filename`), `SIGNED_URL` (`signed_url` only), `OBJECTKEY` (`object_key` + `filename` only; skips download URL generation) |

### JIT Token Authentication

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_JIT_SIGNING_KEY` | No | | HMAC-SHA256 signing key for JIT tokens (`obx_jit_v1.*`). Unset disables JIT auth entirely. |
| `CONSOLE_DASHBOARD_JIT_SIGNING_KEY` | No | | HMAC-SHA256 signing key for Dashboard JIT tokens (`obx_dashboard_jit_v1.*`). Must differ from `CONSOLE_JIT_SIGNING_KEY`. Unset disables Dashboard JIT auth. |

### Worker management

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_HEARTBEAT_INTERVAL_SEC` | No | `5` | Expected worker heartbeat interval (seconds) |
| `CONSOLE_OFFLINE_TTL_SEC` | No | `15` | Seconds before a silent worker is marked offline |
| `CONSOLE_REPLAY_WINDOW_SEC` | No | `60` | Replay window for request deduplication (seconds) |

### Logging

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `CONSOLE_LOG_LEVEL` | No | `info` | `debug` / `info` / `warn` / `error` |
| `CONSOLE_LOG_FORMAT` | No | `json` | `json` / `text` |
| `CONSOLE_LOG_ADD_SOURCE` | No | `false` | Include source file and line |

## Related docs

- [Install](/en/docs/install)
- [Quick Start](/en/docs/quick-start)
- [Architecture](/en/docs/architecture)
