Skip to content

Environment Variable Reference

All environment variables are validated at startup using Zod. If a required variable is missing or invalid, the server refuses to start with a clear error message.

Configuration is loaded from a .env file (via dotenv) and then validated against the schema in src/env.ts.


Database

VariableDefaultRequiredDescription
DB_CLIENTpgNoDatabase driver: pg, mysql, mysql2, sqlite3, better-sqlite3
DB_HOSTlocalhostNoDatabase host
DB_PORT5432NoDatabase port
DB_DATABASEcmsNoDatabase name
DB_USERodp_userNoDatabase user
DB_PASSWORD``NoDatabase password
DB_SSLfalseNoEnable SSL connection
DB_SSL_REJECT_UNAUTHORIZEDtrueNoReject DB server certs that fail verification (set false to allow self-signed)
DB_SSL_CANoPath to a CA bundle (PEM) used to verify the DB server cert — e.g. AWS RDS global-bundle.pem
DB_POOL_MIN0NoMin connection pool size
DB_POOL_MAX10NoMax connection pool size
DB_FILENAMENoSQLite database file path (SQLite only)
DB_LOG_QUERIESfalseNoLog all raw SQL queries to console (requires LOG_LEVEL=debug)

Server

VariableDefaultRequiredDescription
HOST0.0.0.0NoBind address
PORT6688NoHTTP port
PUBLIC_URLhttp://localhost:6688NoPublicly accessible base URL
TRUST_PROXY127.0.0.1/8,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7NoFastify trustProxy — an IP/CIDR list (comma-separated), a hop count (1), or true/false. The default trusts proxies by address (loopback + RFC1918 + ULA) instead of by hop count, so request.ip resolves to the real client IP regardless of how many internal proxy tiers sit in front of the API and whether traffic arrives via the BFF or a direct app call. With a public CDN as the outermost hop, append its ranges; to tighten, replace the list with the exact proxy subnet (e.g. 10.0.1.0/24). Never true in production
SECRETYesJWT signing secret (min 1 character)
ACCESS_TOKEN_TTL15mNoAccess token lifetime (e.g., 15m, 1h)
REFRESH_TOKEN_TTL7dNoRefresh token lifetime (e.g., 7d, 30d)
SESSION_COOKIE_ENABLEDtrueNoEnable session cookie mode
SESSION_COOKIE_NAMEodp_session_tokenNoCookie name for session tokens
LOG_LEVELinfoNotrace, debug, info, warn, error, fatal
LOG_STYLEprettyNopretty (colored output) or raw (JSON)
LOG_FILENoPath to write logs to a file
LOG_REQUESTStrueNoLog each HTTP request
MAX_PAYLOAD_SIZE1mbNoMaximum request body size
ROOT_REDIRECT/server/infoNoWhere / redirects to
NODE_ENVdevelopmentNodevelopment, production, test

CORS

VariableDefaultDescription
CORS_ENABLEDtrueEnable CORS headers
CORS_ORIGIN*Allowed origins (comma-separated or *)
CORS_METHODSGET,POST,PATCH,DELETEAllowed HTTP methods
CORS_ALLOWED_HEADERSContent-Type,AuthorizationAllowed request headers
CORS_EXPOSED_HEADERSContent-RangeExposed response headers
CORS_CREDENTIALStrueAllow credentials
CORS_MAX_AGE18000Preflight cache duration (seconds)

Workflow

VariableDefaultDescription
WORKFLOW_STRICT_NODESfalseWhen true, activating a workflow with an unknown node/action type (or a failing validateConfig) is rejected. When false, unknown nodes are allowed and park to waiting at runtime

Cache

VariableDefaultDescription
CACHE_ENABLEDfalseEnable response caching
CACHE_TTL5mCache entry lifetime
CACHE_STOREmemoryBackend: memory or redis
CACHE_AUTO_PURGEfalseAuto-invalidate on mutations
CACHE_SCHEMAtrueCache database schema
CACHE_SYSTEM_TTL10mSystem cache TTL
CACHE_NAMESPACEodpCache key prefix
CACHE_STATUS_HEADERx-cache-statusResponse header for cache status
CACHE_VALUE_MAX_SIZE1mbMaximum cacheable response size

Redis

VariableDefaultDescription
REDIS_ENABLEDfalseUse Redis for cache and sessions
REDIS_HOST127.0.0.1Redis host
REDIS_PORT6379Redis port
REDIS_PASSWORD``Redis password
REDIS_DB0Redis database index
REDIS_TLSfalseEnable TLS (managed Redis with in-transit encryption / rediss://)
REDIS_TLS_REJECT_UNAUTHORIZEDtrueReject Redis server certs that fail verification (set false to allow self-signed)
REDIS_TLS_CAPath to a CA bundle (PEM) to verify the Redis server cert (self-signed / private CA)

Storage & Files

VariableDefaultDescription
STORAGE_LOCAL_ROOT./uploadsLocal file storage directory
FILES_MAX_UPLOAD_SIZE10mbMaximum upload size per file
FILES_MIME_TYPE_ALLOW_LIST*Allowed MIME types (* = all, or comma-separated list)
FILES_MAX_UPLOAD_CONCURRENCY5Max simultaneous file uploads

Image Transformation (Assets)

VariableDefaultDescription
ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION6000Max output width or height (pixels)
ASSETS_TRANSFORM_MAX_CONCURRENT25Max concurrent image transforms
ASSETS_TRANSFORM_TIMEOUT30Transform timeout (seconds)
ASSETS_CACHE_TTL30mTransformed asset cache TTL
ASSETS_INVALID_IMAGE_SENSITIVITY_LEVELwarningHow to handle corrupt images: none, truncated, error, warning

Email

VariableDefaultDescription
EMAIL_FROMno-reply@example.comDefault sender address
EMAIL_TRANSPORTsmtpTransport: smtp, ses, sendmail
EMAIL_SMTP_HOSTlocalhostSMTP server host
EMAIL_SMTP_PORT587SMTP port
EMAIL_SMTP_USER``SMTP username
EMAIL_SMTP_PASSWORD``SMTP password
EMAIL_SMTP_SECUREfalseEnable TLS/SSL

Rate Limiting

VariableDefaultDescription
RATE_LIMITER_ENABLEDtrueMaster toggle for every limiter (global, per-IP, per-principal, login, email)
RATE_LIMITER_STOREmemoryStore: memory or redis
RATE_LIMITER_POINTS50Anonymous per-IP requests per window (also charged to requests whose token matches no auth strategy)
RATE_LIMITER_DURATION1Per-IP window duration (seconds)
RATE_LIMITER_GLOBAL_ENABLEDtrueEnable global (all-IP) rate limit
RATE_LIMITER_GLOBAL_POINTS1000Global requests per window
RATE_LIMITER_GLOBAL_DURATION1Global window duration (seconds)
RATE_LIMITER_USER_POINTS300Per-user requests per window (roles without service_account)
RATE_LIMITER_USER_DURATION60Per-user window duration (seconds)
RATE_LIMITER_SERVICE_POINTS10000Per-service-account requests per window (roles flagged service_account, e.g. the BFF appApi token — one bucket per service user)
RATE_LIMITER_SERVICE_DURATION60Service-account window duration (seconds)
RATE_LIMITER_LOGIN_POINTS10POST /auth/login attempts per client IP per window
RATE_LIMITER_LOGIN_DURATION60Login window duration (seconds)
RATE_LIMITER_ASSETS_POINTS300Anonymous /assets/* requests per IP per window (media Range streaming)
RATE_LIMITER_ASSETS_DURATION1Assets window duration (seconds)

Authentication Throttling

VariableDefaultDescription
LOGIN_THROTTLE_DELAY1sInitial delay after failed login
LOGIN_THROTTLE_MAX_DELAY30sMaximum backoff delay

WebAuthn / Passkey

VariableDefaultDescription
WEBAUTHN_RP_IDRelying Party ID (domain passkeys bind to). Must never change once credentials are registered. Derives from PUBLIC_URL when unset — set explicitly in split deploys
WEBAUTHN_RP_NAMEODPHuman-readable Relying Party name shown during registration
WEBAUTHN_ORIGINComma-separated browser origins allowed to complete ceremonies (e.g. https://admin.example.com)

Security Events

VariableDefaultDescription
SECURITY_EVENTS_ENABLEDtrueRecord security events (login attempts, permission failures, etc.)

SSRF Protection

VariableDefaultDescription
SSRF_PROTECTION_ENABLEDtrueBlock outbound requests to private/internal addresses
SSRF_ALLOWED_HOSTS``Comma-separated hosts exempted from SSRF protection

Audit Hash Chain

VariableDefaultDescription
AUDIT_HASH_ENABLEDfalseEnable tamper-evident hash chaining for audit records
AUDIT_HMAC_KEY``HMAC key used to sign the audit hash chain
AUDIT_VERIFY_SCHEDULE0 * * * *Cron schedule for the audit chain verification job

AI Engine

VariableDefaultDescription
ASSISTANT_RATE_LIMIT_PER_MIN20Rate limit for the public/anonymous assistant chat (per minute)
ASSISTANT_INGEST_COLLECTIONS``Comma-separated collections to live-sync to the knowledge backend on item create/update/delete; empty disables the listeners
ASSISTANT_LLM_PROVIDERopenai-compatibleLLM provider fallback when an ai_integrations row / app config leaves it blank
ASSISTANT_LLM_BASE_URLhttp://localhost:20128/v1LLM API base URL (OpenAI-compatible)
ASSISTANT_LLM_MODELgpt-4o-miniDefault LLM model
ASSISTANT_LLM_API_KEYLLM API key
KAOS_BASE_URLhttp://localhost:7071KAOS RAG store base URL
KAOS_API_KEYKAOS API key
KAOS_IDENTITY_IDodpKAOS service identity ID
KAOS_IDENTITY_KINDserviceKAOS identity kind
KAOS_IDENTITY_SCOPESknowledge:jobs:write,knowledge:readKAOS identity scopes (comma-separated)
AI_INGEST_MAX_CONTENT_BYTES15728640Max bytes per ingested document (sits just under KAOS's 16MB body limit)
AI_MOCK_RETRIEVALfalseDev-only synthetic retrieval so a RAG flow completes without real KAOS data. Hard-disabled in production
AI_HISTORY_TOKEN_BUDGET3000Conversation-memory history budget (tokens); crossing 50% triggers a rolling summary
AI_ENABLE_CODE_NODEfalseGate for the code flow node (Function() eval — NOT a sandbox)

Configuration Drift Detection

VariableDefaultDescription
DRIFT_DETECTION_ENABLEDfalseEnable configuration drift detection
DRIFT_CHECK_SCHEDULE*/5 * * * *Cron schedule for the drift check job

WebSocket

VariableDefaultDescription
WEBSOCKETS_ENABLEDfalseEnable WebSocket support (opt-in — set true to turn on; the /websocket route is not registered when disabled)
WEBSOCKETS_HEARTBEAT_ENABLEDtrueEnable ping/pong heartbeat (only applies when WEBSOCKETS_ENABLED=true)
WEBSOCKETS_HEARTBEAT_PERIOD30Heartbeat interval (seconds)
WEBSOCKETS_REST_ENABLEDtrueEnable REST-over-WebSocket
WEBSOCKETS_REST_AUTHhandshakeAuth mode: public, handshake, strict
WEBSOCKETS_GRAPHQL_ENABLEDtrueEnable GraphQL over WebSocket
WEBSOCKETS_GRAPHQL_AUTHhandshakeAuth mode: public, handshake, strict

Extensions

VariableDefaultDescription
EXTENSIONS_PATH./extensionsDirectory to load extensions from
EXTENSIONS_MUST_LOAD``Comma-separated list of extensions that must load (server fails if missing)

TUS Resumable Upload

VariableDefaultDescription
TUS_UPLOAD_EXPIRATION10mExpiry for incomplete TUS uploads
TUS_CLEANUP_SCHEDULE0 */6 * * *Cron schedule for TUS cleanup job

Miscellaneous

VariableDefaultDescription
MIGRATIONS_PATH``Path to custom migration files
PRESSURE_ENABLEDtrueEnable server load shedding
METRICS_ENABLEDfalseExpose Prometheus metrics endpoint
METRICS_NAME_PREFIXodp_Prometheus metric name prefix
USER_INVITE_TOKEN_TTL7dInvite token lifetime
EMAIL_VERIFICATION_TOKEN_TTL7dEmail verification token lifetime
REGISTER_STALL_TIME750Minimum response time (ms) for registration to mask user enumeration
USER_REGISTER_URL_ALLOW_LIST``Comma-separated URLs allowed as registration verification redirect targets
QUERYSTRING_MAX_PARSE_DEPTH10Max nesting depth for query string parsing

Example .env

env
# Required
SECRET=your-super-secret-key-change-in-production

# Database
DB_CLIENT=pg
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=odp
DB_USER=odp_user
DB_PASSWORD=odp_password

# Server
PORT=6688
PUBLIC_URL=https://api.example.com
LOG_LEVEL=info
LOG_STYLE=raw

# Cache (Redis)
CACHE_ENABLED=true
CACHE_STORE=redis
REDIS_ENABLED=true
REDIS_HOST=redis
REDIS_PORT=6379

# Email
EMAIL_FROM=no-reply@example.com
EMAIL_TRANSPORT=smtp
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USER=smtp-user
EMAIL_SMTP_PASSWORD=smtp-password
EMAIL_SMTP_SECURE=true

# Storage
STORAGE_LOCAL_ROOT=/data/uploads
FILES_MAX_UPLOAD_SIZE=50mb

# Security
RATE_LIMITER_ENABLED=true
SESSION_COOKIE_ENABLED=true

ODP Internal API Documentation