Skip to content

Environment Variables Reference

All environment variables are validated at startup using Zod schemas defined in packages/server/src/config/env.ts. The server will exit with descriptive errors if validation fails.

Core

VariableRequiredDefaultDescription
NODE_ENVNodevelopmentdevelopment, production, or test
PORTNo3000HTTP server listen port
HOSTNo0.0.0.0HTTP server bind address
LOG_LEVELNoinfoerror, warn, info, http, verbose, debug, silly

Database

VariableRequiredDefaultValidation
MONGODB_URINomongodb://localhost:27017/ai-gatewayMust be a valid URL. See the note below on replica sets.
MONGODB_DB_NAMENoai-gatewayNon-empty string
REDIS_HOSTNolocalhostString
REDIS_PORTNo6379Positive integer
REDIS_PASSWORDProd(empty)Required in production
REDIS_DBNo0Non-negative integer
REDIS_SENTINELSNo(empty)host:port, comma-separated. Set it and the connection follows the master Sentinel elects, ignoring REDIS_HOST/REDIS_PORT. Empty means connect directly.
REDIS_SENTINEL_MASTERNoaigw-redisMust match the name in sentinel monitor <name>
REDIS_SENTINEL_PASSWORDNo(empty)Sentinel’s own requirepass, when it differs from the data password

Authentication

VariableRequiredDefaultValidation
JWT_SECRETYes—Minimum 16 characters. Must not contain placeholder values in production.
JWT_REFRESH_SECRETYes—Minimum 16 characters. Must not contain placeholder values in production.
JWT_ACCESS_EXPIRYNo15mDuration string (e.g., 15m, 1h)
JWT_REFRESH_EXPIRYNo7dDuration string (e.g., 7d, 30d)
ENCRYPTION_KEYYes—Exactly 64 hex characters (256-bit AES key). Sequential patterns rejected in production.

Super Admin Seed

Used by pnpm seed to create the initial administrator account.

VariableRequiredDefaultValidation
SUPER_ADMIN_EMAILNoadmin@ai-gateway.localValid email address
SUPER_ADMIN_PASSWORDYes—12+ characters, must include uppercase, lowercase, digit, and special character

Semantic Cache

VariableRequiredDefaultDescription
CACHE_EMBEDDING_MODELNonomic-embed-textEmbedding model for cache similarity
CACHE_SIMILARITY_THRESHOLDNo0.96Cosine similarity threshold (0.0-1.0)
CACHE_DEFAULT_TTL_SECONDSNo86400Cache entry TTL in seconds (default: 24 hours)

Rate Limiting

VariableRequiredDefaultDescription
RATE_LIMIT_WINDOW_MSNo60000Window duration in milliseconds
RATE_LIMIT_MAX_PER_WINDOWNo60Max requests per window, per IP, on /v1/* and the public auth routes
ADMIN_RATE_LIMIT_MAX_PER_WINDOWNo600Max requests per window on the admin API, counted per operator rather than per IP

The admin console is a different traffic shape from the gateway: one page view is ten to twenty API calls, and an operator moving around the console does that several times a minute. It is therefore counted per signed-in operator, not per IP — otherwise every operator behind one office NAT shares a single budget, and ordinary browsing produces 429s that pages can render as empty collections rather than as failures.

Raise ADMIN_RATE_LIMIT_MAX_PER_WINDOW if operators see panels that fail to load under normal use. /api/admin/auth/* and the SSO routes are deliberately excluded and keep the per-IP limit, because that is where brute-force protection belongs.

CORS and Networking

VariableRequiredDefaultDescription
CORS_ORIGINSNo(empty)Comma-separated allowed origins (each must be a valid URL)
SOCKET_CORS_ORIGINNohttp://localhost:3001The origin the admin console is served from. The console opens a WebSocket for live dashboard and audit updates; if this does not match, the connection is refused and the console simply stops updating without reporting why.
ADMIN_URLNohttp://localhost:3001Admin dashboard URL
SSO_CALLBACK_BASE_URLSet it in production(falls back to ADMIN_URL)The gateway’s public origin, which is what the redirect URI registered with your identity provider must match. Taking it from the request instead would be a Host-header injection, so it is never inferred in production. The Settings page shows the resulting URIs — copy them from there rather than assembling them.
TRUST_PROXYBehind a proxy(trust nothing)How many reverse proxies sit in front of the gateway. See below — this decides who every caller appears to be.

TRUST_PROXY

The gateway identifies a caller by the address the connection came from. When it sits behind nginx, an ingress controller or a load balancer, that address is the proxy’s, and the caller’s real one arrives in the X-Forwarded-For header — which the gateway ignores until you tell it how far to trust.

Four things read the caller’s address:

  • API-key IP allow-lists (allowedIps) compare against it.
  • The per-IP rate limit on /api/admin/auth/* and the SSO routes, which is the deployment’s brute-force protection.
  • The audit trail, which records it as the actor’s address.
  • The session list on each operator’s profile page.

Left unset behind a proxy, all four see the proxy’s address on every request: an allow-list compares against a constant, every client in the world shares one rate-limit bucket, and the audit trail records a single address for every actor. The gateway warns about this at boot in production, because nothing else in the log mentions it.

ValueMeaning
(unset), false, 0Trust nothing. Correct only when the gateway is exposed directly.
1One proxy. This is the bundled docker-compose.prod.yml and both swarm stacks.
2Two — e.g. a CDN in front of your own nginx. Count everything that appends to X-Forwarded-For.
10.0.0.0/8, 10.1.2.3Trust these proxy addresses or CIDRs specifically.
trueTrust the whole chain. Avoid.

Count hops rather than using true. A hop count is applied from the connection inwards, so an entry the client invented is never the one that wins. true takes the left-most entry instead — which is whatever the caller chose to send, making an IP allow-list satisfiable with a single header. Counting too high has the same effect, so raise the number only for proxies that genuinely exist.

Background Workers

VariableRequiredDefaultDescription
BULLMQ_PREFIXNoaigwRedis key prefix for BullMQ queues

S3 Backup

All S3 variables are optional. When not configured, audit log backups are stored locally.

VariableRequiredDefaultDescription
S3_BUCKETNo—S3 bucket name
S3_REGIONNous-east-1AWS region
S3_ACCESS_KEY_IDNo—AWS access key ID
S3_SECRET_ACCESS_KEYNo—AWS secret access key
S3_PREFIXNobackupsKey prefix within the S3 bucket

SIEM Export

All SIEM variables are optional. When not configured, SIEM export is disabled.

VariableRequiredDefaultDescription
SIEM_TYPENo—Export type: splunk, elk, or webhook
SIEM_URLNo—SIEM endpoint URL
SIEM_TOKENNo—Authentication token
SIEM_BATCH_SIZENo100Events per batch

Audit retention

Set on the worker, which is the only writer of audit entries.

VariableRequiredDefaultDescription
AUDIT_LOG_RETENTION_DAYSNo365Days an audit entry is kept before the TTL index removes it. 0 disables expiry entirely.

Observability (OpenTelemetry)

All optional. When OTEL_EXPORTER_OTLP_ENDPOINT is unset, OpenTelemetry is a no-op with zero overhead. When set, the server and worker export traces, metrics, and logs over OTLP/HTTP; the collector base URL has /v1/{traces,metrics,logs} appended. See Observability for the full metric list and Grafana/Prometheus assets.

VariableRequiredDefaultDescription
OTEL_EXPORTER_OTLP_ENDPOINTNo—OTLP collector base URL (e.g. http://otel-collector:4318). Unset disables OpenTelemetry export.
OTEL_SERVICE_NAMENoai-gateway / ai-gateway-workerOverrides the service.name resource attribute (worker defaults to ai-gateway-worker).
OTEL_METRIC_EXPORT_INTERVAL_MSNo30000Metric export interval in ms when OTLP is enabled.

For full ESM auto-instrumentation, start each process with node --import ./dist/telemetry/otel.js ./dist/index.js. Prometheus metrics remain available at GET /metrics regardless of OTLP configuration.

Encryption Key Source (KMS / BYOK)

VariableRequiredDefaultDescription
KEY_PROVIDERNoenvSource of the data-encryption key. env uses ENCRYPTION_KEY. A misconfigured value fails loudly rather than silently falling back. (vault / awskms are extension points, not yet implemented.)

Budget Alert Delivery

All optional; a budget’s notifyVia channel is a no-op unless the matching variables are set. Delivery is best-effort and isolated per channel. See Budgets.

VariableRequiredDefaultDescription
SMTP_HOSTNo—SMTP server host (enables email alerts).
SMTP_PORTNo587SMTP port.
SMTP_SECURENofalseUse TLS on connect (set true for port 465).
SMTP_USERNo—SMTP username.
SMTP_PASSNo—SMTP password.
SMTP_FROMNogatewyse@localhostFrom address for alert emails.
BUDGET_ALERT_WEBHOOK_URLNo—Webhook endpoint for budget alerts (HMAC-signed when a secret is set).
BUDGET_ALERT_WEBHOOK_SECRETNo—Secret used to HMAC-sign webhook payloads.
SLACK_WEBHOOK_URLNo—Slack incoming-webhook URL for budget alerts.

License (EE)

The Enterprise Edition gates service on an Ed25519-signed license JWT issued by the 137 & Co. platform. If LICENSE_TOKEN is missing or invalid when NODE_ENV=production, the server still boots but locks out: every request except health probes, admin sign-in, and the licence endpoints is refused until a valid licence is installed. It never exits, so recovery never requires shell access.

VariableRequiredDefaultDescription
LICENSE_TOKENProd—Ed25519-signed JWT issued by the 137 & Co. platform. Required in production.
LICENSE_PUBLIC_KEYSWhen LICENSE_TOKEN is set—One or more PEM-encoded public keys joined with ;; (the double-semicolon delimiter is used because newlines inside env values are unreliable across shells and Docker).
LICENSE_SERVER_URLNo—Points the daily revocation check at the licence server; set it on every non-air-gapped deployment. Air-gap is a signed licence claim (Government edition), never a configuration setting — unsetting this does not make a deployment air-gapped.
LICENSE_PHONE_HOME_INTERVAL_MSNo86400000Polling interval (ms) for the revocation check. Default is 24 hours.
LICENSE_GRACE_PERIOD_MSNo604800000How long a revoked licence continues to serve before the deployment locks out. Default is 7 days, measured from the issuer’s revocation timestamp.
GATEWYSE_LICENSE_FINGERPRINTNo—Optional hardware-fingerprint override. Read directly via process.env in packages/license/src/fingerprint.ts (it is not part of the Zod env schema), because the license verifier runs before env validation. When set, it overrides the auto-derived machine fingerprint used for hardware-bound licenses.

The license verifier runs before the Zod env validator and Winston logger because both depend on environment that has not yet been validated at bootstrap time. For that reason LICENSE_* and GATEWYSE_LICENSE_FINGERPRINT are read straight from process.env and do not appear in the Zod env schema. See packages/server/src/services/license.service.ts for the boot sequence.

Observability

VariableRequiredDefaultDescription
METRICS_TOKENNo(unset)When set, GET /metrics requires Authorization: Bearer <token> and answers 401 without it. Minimum 16 characters.

/metrics is mounted ahead of all authentication, because a Prometheus scraper is not a session and cannot refresh a credential. It publishes per-provider and per-model spend and token totals, so it should not be reachable from outside the deployment.

The bundled nginx returns 404 for /metrics, so the Docker Compose topology is already closed. The Kubernetes manifests expose the server directly — set METRICS_TOKEN there, or keep the path off the ingress. In production the server logs a warning at boot when it is unset, because nothing else in the log mentions the endpoint either way.

Add it to a Prometheus scrape config with:

scrape_configs:
- job_name: gatewyse
authorization:
credentials: <token>
static_configs:
- targets: ['gatewyse:3000']

API Documentation

VariableRequiredDefaultDescription
ENABLE_SWAGGERNofalseWhen true, exposes the Swagger UI at /docs. In production this is off by default; set to true to enable.

Provider API Keys

Provider API keys are managed through the admin dashboard (or the admin API) and stored in the deployment provider catalogue, encrypted at rest with AES-256-GCM — the gateway resolves them from the database at request time. There is no runtime code path that reads OPENAI_API_KEY, ANTHROPIC_API_KEY, etc. from the environment for live routing.

The variable names below are listed for reference only (e.g. for local development scripts, seeding, or smoke tests); setting them does not configure a provider for the gateway:

Terminal window
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_AI_API_KEY=AIza...
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
GROQ_API_KEY=gsk_...
MISTRAL_API_KEY=...
COHERE_API_KEY=...
DEEPSEEK_API_KEY=...
TOGETHER_API_KEY=...
FIREWORKS_API_KEY=...
PERPLEXITY_API_KEY=pplx-...
AI21_API_KEY=...
HUGGINGFACE_API_KEY=hf_...
XAI_API_KEY=...
CEREBRAS_API_KEY=...
SAMBANOVA_API_KEY=...
REPLICATE_API_TOKEN=r8_...
ELEVENLABS_API_KEY=...
ASSEMBLYAI_API_KEY=...

Production Security Checks

When NODE_ENV=production, the server enforces additional validation at startup:

  1. JWT_SECRET must not contain known placeholder strings
  2. JWT_REFRESH_SECRET must not contain known placeholder strings
  3. ENCRYPTION_KEY must not use sequential hex patterns (e.g., 0123456789abcdef repeated)
  4. REDIS_PASSWORD must be set (non-empty)

If any check fails, the server exits with a descriptive error message.