LumiBaseDocs

Environment Variables Reference

For AI agents: All required variables must be set before starting the CMS API. Missing required variables will cause startup to fail with an explicit error message.

This page documents every environment variable and Cloudflare binding used by LumiBase.


Core runtime

VariableRequiredDefaultDescription
LUMIBASE_ENVEnvironment label: development, staging, production
LUMIBASE_RUNTIMEDocker onlycloudflaredocker for Node.js/Docker; Cloudflare Workers infers from bindings
JWT_SECRETSecret for signing/verifying application JWTs. Min 32 chars. For Cloudflare production, set with wrangler secret put JWT_SECRET --env production; never commit or place in [env.production.vars].
LUMIBASE_DEV_AUTHLocal dev onlyfalseSet to true to bypass Logto auth in local dev. Never enable in production; pnpm release:check fails if production resolves to true.
LUMIBASE_REALTIME_ENABLEDtrueSet to false to disable WebSocket at deployment level
LUMIBASE_ADMIN_PATH(random)Custom path for Studio admin panel (security through obscurity)
VITE_LUMIBASE_ALLOW_ADMIN_PATH_REDIRECTSetup/debug onlyfalseClient-side opt-in that allows convenience redirects to the private admin path. Keep unset in production except for a temporary controlled setup/debug window.

The admin path is private operational state. Do not expose it through VITE_* environment variables or client build metadata, and do not automatically redirect public/setup routes to it in production. See Private admin path.


Authentication (Logto)

VariableRequiredDescription
LOGTO_ENDPOINTLogto instance URL (e.g., https://your-tenant.logto.app)
LOGTO_APP_IDLogto application ID
LOGTO_APP_SECRETLogto application secret
LOGTO_JWKS_URIOverride JWKS URL (auto-derived from LOGTO_ENDPOINT if not set)
CF_ACCESS_CERTS_URLCF Access onlyCloudflare Access JWKS URL for admin tunnel auth
CF_ACCESS_AUDIENCECF Access onlyCloudflare Access application audience tag

Database

VariableRequiredDescription
DATABASE_URLDocker onlyPostgreSQL connection string (e.g., postgres://user:pass@host:5432/lumibase)
DATABASE_POOL_MINMinimum DB pool connections (default: 2)
DATABASE_POOL_MAXMaximum DB pool connections (default: 10)
DATABASE_SSLtrue to require SSL for DB connection

For Cloudflare Workers, use the HYPERDRIVE binding (see Cloudflare Bindings).


Cache

VariableRequiredDescription
REDIS_URLDocker onlyRedis connection string (e.g., redis://localhost:6379)
CACHE_TTL_SCHEMASchema cache TTL in seconds (default: 60)
CACHE_TTL_PERMISSIONSPermission cache TTL in seconds (default: 300)
CACHE_TTL_SETTINGSSettings cache TTL in seconds (default: 60)

Object storage

VariableRequiredDescription
S3_ENDPOINTDocker/S3 onlyS3-compatible endpoint URL (e.g., MinIO: http://localhost:9000)
S3_ACCESS_KEY_IDDocker/S3 onlyS3 access key
S3_SECRET_ACCESS_KEYDocker/S3 onlyS3 secret key
S3_BUCKETDocker/S3 onlyStorage bucket name (default: lumibase-media)
S3_REGIONS3 region (default: us-east-1)
S3_PUBLIC_URLPublic base URL for assets (e.g., CDN URL pointing to the bucket)

Search (MeiliSearch)

VariableRequiredDescription
MEILISEARCH_URLIf search enabledMeiliSearch instance URL
MEILISEARCH_API_KEYIf search enabledMeiliSearch master or search API key

AI Copilot

VariableRequiredDescription
LLM_PROVIDERLLM provider: openai, anthropic, claude, gemini, nvidia, vertex, workers-ai, echo (default: echo)
OPENAI_API_KEYIf openai providerOpenAI API key
ANTHROPIC_API_KEYIf anthropic / claude providerAnthropic API key
GEMINI_API_KEYIf gemini providerGoogle Gemini API key
NVIDIA_API_KEYIf nvidia providerNVIDIA hosted-inference key (build.nvidia.com / NIM). Billed by NVIDIA.
NVIDIA_BASE_URLOverride the NVIDIA endpoint — e.g. a self-hosted NIM container (http://nim:8000/v1). Defaults to https://integrate.api.nvidia.com/v1.
VERTEX_ACCESS_TOKENIf vertex providerGoogle Cloud OAuth 2.0 bearer (gcloud auth print-access-token). Tokens expire (~1h). Billed to Google Cloud, not AWS.
VERTEX_PROJECT_IDIf vertex providerGoogle Cloud project id that owns the Vertex AI models.
VERTEX_LOCATIONVertex AI region (default: us-central1).
LLM_MODELModel name override (e.g., gpt-4.1-nano, claude-3-5-haiku-latest, gemini-3.5-flash, meta/llama-3.1-8b-instruct)
WORKERS_AI_GATEWAYWorkers AI onlyCF Workers AI gateway URL

Provider ↔ billing: nvidia and vertex call external clouds — NVIDIA and Google Cloud respectively — so their usage is not covered by AWS credit. nvidia (or a self-hosted NIM via NVIDIA_BASE_URL) and MeiliSearch are the pieces that pair naturally with AWS-hosted infrastructure.


Email (Resend)

VariableRequiredDescription
RESEND_API_KEYIf email enabledResend API key for transactional email
EMAIL_FROMIf email enabledSender address (e.g., noreply@yourdomain.com)

SCIM provisioning

VariableRequiredDescription
SCIM_TOKENIf SCIM enabledBearer token for /scim/v2/ endpoint authentication

Pressure limiter (Docker / Node.js)

The Docker CMS process includes an overload guard for the Node.js event loop. When enabled and the process is saturated, API requests fail fast with HTTP 503, a SERVICE_UNAVAILABLE JSON envelope, Retry-After, and X-Lumi-Overload instead of queueing until the container becomes unresponsive. The guard bypasses /health and /metrics by default so operators can still inspect the instance.

VariableRequiredDefaultDescription
LUMIBASE_PRESSURE_LIMITER_ENABLEDDocker onlytrueEnables the Node.js overload guard. Set false only as a temporary mitigation while you scale or optimize the overloaded path.
LUMIBASE_PRESSURE_LIMITER_SAMPLE_INTERVAL250Sampling interval in milliseconds for event-loop pressure checks.
LUMIBASE_PRESSURE_LIMITER_MAX_EVENT_LOOP_DELAY1000Maximum observed event-loop delay in milliseconds before API traffic receives 503. Set false to disable this threshold.
LUMIBASE_PRESSURE_LIMITER_MAX_EVENT_LOOP_UTILIZATIONfalseOptional utilization threshold such as 0.99. Disabled by default because sustained useful CPU work can otherwise produce noisy rejections.
LUMIBASE_PRESSURE_LIMITER_RETRY_AFTER5Seconds advertised in the Retry-After response header.
LUMIBASE_PRESSURE_LIMITER_EXCLUDED_PATHS/health,/metricsComma-separated path prefixes that should keep serving during overload checks.

Rate limiting

A fixed-window throttle guards the authenticated API. It keys per principal (user → API key → IP) and is scoped per site. When exceeded it returns HTTP 429 with a RATE_LIMITED envelope plus X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After. It fails open if the cache is unavailable, so it is defence-in-depth rather than a hard quota.

Large imports can trip the default budget. Raise LUMIBASE_RATE_LIMIT_MAX and prefer the bulk endpoint — see Data import.

VariableRequiredDefaultDescription
LUMIBASE_RATE_LIMIT_MAX300Max requests per window per principal, per site.
LUMIBASE_RATE_LIMIT_WINDOW_S60Window length in seconds.
LUMIBASE_RATE_LIMIT_DISABLED(unset)Set to true to disable the throttle entirely.

GraphQL

Every GraphQL operation is validated before it runs against a depth limit and a static cost limit, rejecting abusively deep or wide queries at parse time (CWE-770). Depth is a compile-time constant (12); cost is tunable. Raise LUMIBASE_GQL_MAX_COST if a legitimate query is rejected. See graphql-api-spec.md.

VariableRequiredDefaultDescription
LUMIBASE_GQL_MAX_COST1000Max static cost accepted per operation.
LUMIBASE_GQL_DEFAULT_LIST_SIZE20Cost multiplier for a list field with no literal pagination argument (or a variable one).
LUMIBASE_GQL_MAX_LIST_MULTIPLIER100Upper clamp on any single list field's cost multiplier.

Observability

VariableRequiredDescription
PROMETHEUS_ENABLEDDocker onlytrue to expose /metrics endpoint
LOG_LEVELLog level: debug, info, warn, error (default: info)
LOG_FORMATjson (default) or pretty (local dev)

Cloudflare Bindings

Configure these in apps/cms/wrangler.toml (not environment variables):

BindingTypePurpose
HYPERDRIVEHyperdrivePooled PostgreSQL connections
CONFIG_CACHEKV NamespaceSchema, permission, and settings cache
MEDIAR2 BucketMedia/file object storage
SITE_ROOMDurable ObjectPer-site WebSocket coordination (realtime)
AIWorkers AIWorkers AI binding for workers-ai LLM provider
toml
# wrangler.toml excerpt
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "<your-hyperdrive-id>"

[[kv_namespaces]]
binding = "CONFIG_CACHE"
id = "<your-kv-namespace-id>"

[[r2_buckets]]
binding = "MEDIA"
bucket_name = "lumibase-media"

[durable_objects]
bindings = [{ name = "SITE_ROOM", class_name = "SiteRoom" }]

Security checklist

Before deploying to production, verify:

  • JWT_SECRET is at least 32 characters and stored as a Wrangler Secret or Docker secret
  • LUMIBASE_DEV_AUTH is NOT set to true
  • Database credentials are stored as secrets, not in .env files committed to git
  • S3_SECRET_ACCESS_KEY is stored as a secret
  • RESEND_API_KEY is stored as a secret
  • CORS is configured to allow only your Studio and consumer domains
Last modified: 23/07/2026