Environment variables¶
The core reads its configuration from environment variables at startup. There are two groups with different failure behaviour:
- Core variables are validated strictly. A missing required value or an invalid one aborts the start with a message naming the variable.
- Observability variables never abort. An invalid value prints an error
prefixed
[observability]and leaves observability disabled for the life of the process.
Legend: required optional
Core¶
DATABASE_URL required¶
PostgreSQL connection string.
No default. The format is not validated beyond being a non-empty string; a
wrong DSN shows up as [db] waiting for postgres... for 30 seconds followed
by a crash. For a Cloud SQL Unix socket use
postgresql://user:pass@localhost/dbname?host=/cloudsql/<connectionName>
(the localhost is mandatory filler). See Database.
MASTER_ENCRYPTION_KEY required¶
Key used to encrypt provider credentials at rest with AES-256-GCM.
- Format: exactly 64 hexadecimal characters (32 bytes). Anything else
aborts with
must be 64 hex characters (32 bytes). A trailing newline counts as a character. - Generate:
openssl rand -hex 32 - Cannot be rotated. Changing it makes every stored provider credential undecryptable; each provider has to be re-created or edited with its credentials again. Back it up with the database.
PORT optional¶
Listening port. Default 3000. Must be an integer between 0 and 65535.
Platforms such as Cloud Run inject it for you.
NODE_ENV optional¶
One of development, test, production. The image sets production.
Any other value aborts. Its only effect is the default of LOG_REQUESTS.
LOG_REQUESTS optional¶
true writes one line per HTTP request to stdout:
[req] POST /v1/proxy-apps/…/openai/v1/chat/completions 200 843ms
[req] POST /v1/proxy-apps/…/openai/v1/chat/completions 200 12043ms (aborted)
Default: on when NODE_ENV=development, off otherwise. An explicit value
wins. Malformed JSON requests are logged too. See
Request logging.
MAX_UPLOAD_SIZE optional¶
Ceiling for the body of a file upload request. Default 50mb. Accepts
bytes-style strings: 10mb, 2gb, 524288000.
- Applies only to the upload routes:
…/openai/files,…/openai/v1/files,…/gemini/upload/v1beta/files,…/gemini/upload/v1/files. - The whole upload is held in RAM for the duration of the request. Size the container accordingly, or lower this value.
- An empty string is not the default: it removes the limit entirely.
- JSON bodies have a separate, fixed limit of 10 MB that is not configurable.
TRUST_PROXY optional¶
true makes the core trust X-Forwarded-For and X-Forwarded-Proto from
the hop in front of it. Default false.
Set it to true only when a reverse proxy or load balancer terminates
TLS in front of the core. It affects:
- the client IP seen by the firewall policy and recorded as
client_ipin traces; - the protocol used to rewrite Gemini resumable-upload URLs.
With false and a proxy in front, every client looks like the proxy. With
true and no proxy, a client can forge its IP. See
Reverse proxy & TLS.
PUBLIC_BASE_URL optional¶
Public URL of the core, e.g. https://axium-api.your-domain.com. No default.
Used for one thing: rewriting the x-goog-upload-url header that Google
returns in the first step of a Gemini resumable upload, so the second step
also goes through Axium. When unset, the core builds the URL from the request
(protocol://host), which is only wrong when something in front terminates
TLS. A trailing slash is removed.
AXIUM_LICENSE optional¶
Your license key, 40 hexadecimal characters. Validated once at startup against the Axium Lab license service. Today an absent or invalid license is only logged; the process starts anyway. See License.
AXIUM_LICENSE_FILE optional¶
Path to a JSON file holding the license, read only when AXIUM_LICENSE is
empty. Default /license/license.json. Format:
A missing file means "no license". A file without a non-empty license
string logs an error. Intended for mounting the key as a secret volume.
AXIUM_METASERVER optional¶
Base URL of the Axium Lab metadata service. Default
https://meta.axium-lab.com/v1. Must be a valid URL or the start aborts.
Used for GET {base}/license/check/{key} and POST {base}/telemetry.
Only change it if Axium Lab gives you a different endpoint.
TELEMETRY_ENABLED optional¶
Default true. Once per process start (never periodically) the core sends
one anonymous usage snapshot to the metadata service. It never blocks or
fails the start, and nothing is sent when the schema is not installed.
What the snapshot contains
Aggregates over the whole history of the installation, no names, no prompts, no money:
{
"telemetry_schema": 1,
"install_id": "<random uuid generated at install>",
"app_version": "3.1.0",
"schema_version": 3,
"installed_at": "…", "sent_at": "…",
"traffic": {
"requests": 0, "errors": 0, "denied": 0, "streamed": 0,
"tokens_in": 0, "tokens_out": 0, "tokens_cached": 0,
"tokens_reasoning": 0, "tokens_saved": 0,
"avg_latency_ms": null, "max_latency_ms": null, "avg_ttfb_ms": null
},
"coverage": { "first_day": "YYYY-MM-DD", "last_day": "YYYY-MM-DD" }
}
Observability¶
These select and configure the per-request trace destination. The full behaviour is in the Observability section.
OBSERVABILITY_TYPE optional¶
| Value | Effect |
|---|---|
unset, empty, none |
Traces are not recorded. Default. |
postgres |
Traces are written to a PostgreSQL database and readable through the API. |
http |
Traces are POSTed in batches to an HTTP endpoint. |
Any other value logs unknown OBSERVABILITY_TYPE "<x>" (expected: postgres, http), disabled.
OBSERVABILITY_DB_POSTGRESQL required with postgres¶
Connection string of the database that receives the traces. It can be the
main Axium database or a separate one. Empty with OBSERVABILITY_TYPE=postgres
disables observability with a log line. The core opens a separate pool
for it (max 8 connections).
OBSERVABILITY_HTTP_URL required with http¶
URL that receives one POST per batch. Not probed at startup: a wrong URL
shows up on the first flush as a throttled error log.
OBSERVABILITY_HTTP_FORMAT optional¶
envelope (default) or ndjson. See
Formats & event schema.
OBSERVABILITY_HTTP_HEADERS optional¶
A flat JSON object of string headers added to every POST, typically for authentication:
OBSERVABILITY_HTTP_HEADERS='{"Authorization":"Bearer xxx"}'
OBSERVABILITY_HTTP_HEADERS='{"DD-API-KEY":"…"}'
They are applied after Axium's own headers, so they can override
content-type and x-axium-trace-version. Anything that is not a JSON
object of strings disables observability with a log line.
Variables that do not exist¶
To save you a search: there is no configuration for CORS (it is open, see
Security), rate limiting, provider timeouts or retries, log
level or JSON logging, JWT secrets, OpenTelemetry (OTEL_*), Langfuse or
feature flags. API_URL belongs to the ui, not the core; see
Web console.
Quick reference¶
| Variable | Required | Default | Invalid value |
|---|---|---|---|
DATABASE_URL |
yes | — | aborts |
MASTER_ENCRYPTION_KEY |
yes | — | aborts |
PORT |
no | 3000 |
aborts |
NODE_ENV |
no | production (image) |
aborts |
LOG_REQUESTS |
no | off in production | aborts |
MAX_UPLOAD_SIZE |
no | 50mb |
aborts |
TRUST_PROXY |
no | false |
aborts |
PUBLIC_BASE_URL |
no | request host | — |
AXIUM_LICENSE |
no | — | logged |
AXIUM_LICENSE_FILE |
no | /license/license.json |
logged |
AXIUM_METASERVER |
no | https://meta.axium-lab.com/v1 |
aborts |
TELEMETRY_ENABLED |
no | true |
aborts |
OBSERVABILITY_TYPE |
no | off | observability disabled |
OBSERVABILITY_DB_POSTGRESQL |
with postgres |
— | observability disabled |
OBSERVABILITY_HTTP_URL |
with http |
— | observability disabled |
OBSERVABILITY_HTTP_FORMAT |
no | envelope |
observability disabled |
OBSERVABILITY_HTTP_HEADERS |
no | {} |
observability disabled |