Environment Variables
Every environment variable OKE reads — connection URLs, driver overrides, secrets, and CLI flags.
OKE reads environment variables at boot for connection detail and secrets — never for
behavior you could declare in oke.config.ts. Under oke dev, Compose writes these
into .env.local; this page is the full map.
The one rule
Put drivers, images, and locale lists in oke.config.ts. Use env vars for URLs, credentials, and
runtime posture the host injects — not for inventing new behavior.
Smallest Example
Let Compose write the map
oke devCompose fills .env.local with DATABASE_URL, Redis, S3, and vault keys for the
pinned images.
Override one URL when needed
export DATABASE_URL=postgres://user:pass@db:5432/okeConventional names win over OKE_* aliases, then built-in defaults.
Precedence
Resolution order
For anything with both an OKE_* variable and a conventional one (like DATABASE_URL), the
conventional variable wins first, then the OKE_* form, then the built-in default.
SQL store
| Variable | Used for | Default when unset |
|---|---|---|
DATABASE_URL | Postgres connection (postgres store / clock / journal / Console operator plane, drizzle-kit). App tables stay in public; Console operators/sessions use schema oke_console on the same database. When PgDog is pinned, this points at the pooler (:6432). | postgres://localhost:5432/oke |
OKE_STORE_SQL_URL | Direct SQL URL (Postgres host, even when PgDog fronts the app). Also used by Console when DATABASE_URL is unset. | — |
OKE_PGDOG_URL | PgDog pooler URL (same value as DATABASE_URL when both are present) | — |
OKE_PGLITE_URL | PGlite data dir or memory:// (pglite driver; required for store.sql.test) | memory:// in test; else .oke/pgdata |
OKE_SQL_DRIVER | Force the sql driver id at boot | config map |
oke test sets OKE_PGLITE_URL=memory:// when unset. The sqlite driver and OKE_SQLITE_URL are removed.
Index store
| Variable | Used for | Default when unset |
|---|---|---|
OKE_INDEX_DRIVER | Force the index driver id | config map |
OKE_STORE_INDEX_URL | Meilisearch base URL (meilisearch driver) | — |
OKE_STORE_INDEX_KEY | Meilisearch API / master key (meilisearch driver) | MEILI_MASTER_KEY |
KV store
| Variable | Used for | Default when unset |
|---|---|---|
REDIS_URL | Cache Redis connection | driver default |
OKE_STORE_KV_URL | Explicit cache KV URL override | — |
OKE_KV_DRIVER | Force the kv driver id | config map |
Files store
| Variable | Used for | Default when unset |
|---|---|---|
S3_BUCKET | Bucket name (s3 driver) | — |
S3_ENDPOINT | S3-compatible endpoint (RustFS) | — |
S3_ACCESS_KEY_ID | Access key | — |
S3_SECRET_ACCESS_KEY | Secret key | — |
S3_REGION | Region | — |
S3_SESSION_TOKEN | Session token (temporary creds) | — |
OKE_STORE_FILES_DB | Explicit files location override | — |
OKE_FILES_DRIVER | Force the files driver id | config map |
Vault
Built-in store uses OKE_VAULT_MASTER_KEY (or --key / stdin on CLI). Managed providers use the
vars below — see Vault for which each id needs.
| Variable | Used for | Default when unset |
|---|---|---|
OKE_VAULT_PROVIDER | Managed backend (aws-secrets-manager · azure-key-vault · gcp-secret-manager · doppler · 1password) | — (platform-injected) |
OKE_VAULT_REGION | Cloud region (AWS Secrets Manager; GCP user-managed replication) | — |
OKE_VAULT_MOUNT | Scope: AWS/Azure prefix, GCP project[/prefix], Doppler project/config, 1Password vault name | — |
OKE_VAULT_MASTER_KEY | Built-in vault master key (base64) | — |
OKE_VAULT_URL | Azure Key Vault URI, 1Password Connect host, optional Doppler origin | — |
OKE_VAULT_TOKEN | Doppler service/personal token, 1Password Connect token | — |
Channel (email) — boot binder
Read when drivers.channel.email resolves to that driver id.
| Variable | Used for |
|---|---|
SMTP_URL | smtp — full SMTP URL (smtp://…) |
SMTP_USER | Overrides the user embedded in SMTP_URL |
SMTP_PASSWORD | Overrides the password in SMTP_URL |
OKE_CHANNEL_EMAIL_URL | Alternative to SMTP_URL |
RESEND_API_KEY | resend API key |
SNDR_API_KEY | sndr API key |
SNDR_BASE_URL | Optional SNDR API origin (default api.sndr.sh) |
TAQNYAT_MAIL_TOKEN | taqnyat-mail bearer token (Email-enabled) |
TAQNYAT_CAMPAIGN | taqnyat-mail campaign name |
Channel (SMS) — boot binder
Read when drivers.channel.sms resolves to that driver id (console opens nothing).
| Variable | Used for |
|---|---|
TAQNYAT_BEARER_TOKEN | taqnyat bearer token |
TAQNYAT_TOKEN | Alias for TAQNYAT_BEARER_TOKEN |
TAQNYAT_SENDER | Taqnyat pre-approved sender id |
MSEGAT_USERNAME | msegat account username |
MSEGAT_API_KEY | msegat API key |
MSEGAT_SENDER | Msegat pre-approved sender id |
UNIFONIC_APPSID | unifonic AppSid |
UNIFONIC_APP_SID | Alias for UNIFONIC_APPSID |
UNIFONIC_SENDER | Unifonic SenderID (optional) |
WhatsApp (wa-cloud) and push (webpush / fcm) are not opened from env at
boot — pass them on BootOptions.channel.drivers with their open options.
Live test gates (opt-in, contributors)
Provider-quota-burning live suites in the okengine repo are double-gated: the medium flag plus that provider's real credentials — credentials alone never send. App projects can ignore these.
| Variable | Used for |
|---|---|
OKE_SMS_LIVE | =1 allows live SMS provider tests (e.g. Taqnyat OTP) |
OKE_EMAIL_LIVE | =1 allows live email provider tests (e.g. Taqnyat Mail) |
AI providers
| Variable | Used for | Default when unset |
|---|---|---|
ANTHROPIC_API_KEY | anthropic driver credential | — |
ANTHROPIC_MODEL | Model override for the anthropic driver | — |
OPENAI_API_KEY | openai-compatible driver credential | — |
OPENAI_BASE_URL | openai-compatible base URL | OpenAI cloud |
OKE_AI_DRIVER | Force the AI driver id (honoured under Compose / oke dev) | config map |
OKE_AI_URL | openai-compatible base URL (must end in /v1) — BYO; Compose does not manage inference | — |
OKE_AI_MODEL | Default model id for openai-compatible / setup bindings | — |
OKE_AI_VISION_MODEL | Vision model id written by oke ai setup (logical ai.model("vision")) | — |
OKE_AI_EMBED_MODEL | Embedding model id written by oke ai setup | — |
Framework behavior
| Variable | Used for |
|---|---|
OKE_DOCKER | "1" marks Compose / oke dev posture (set by the CLI) |
OKE_DB_AUTO_PUSH | Overrides db.autoPush at boot |
OKE_DRIZZLE_DIALECT | "postgresql" for drizzle-kit overlays (templates hardcode it) |
OKE_DEV_REQUEST_LOG | "1" logs requests during oke dev (set by the CLI) — surface, flow, status, timestamp, run id |
OKE_CONSOLE_SECRET | Console operator-session signing secret (HMAC) — set in production; else .oke/console.secret. Not a Vault contract. |
OKE_CONSOLE_AUTH_STORE | "1" lists the operator-plane oke_console schema in Store browse (read-only). Hidden by default. |
OKE_RUNS_INGEST_URL | Host → Console WideEvent ingest URL (oke dev sets this on the app child). Enables a memory runs store + push. |
OKE_RUNS_INGEST_SECRET | Shared secret for POST /console/runs/ingest (x-oke-runs-ingest header). Minted by oke dev; never return events. |
PORT | App port in production containers (default 6530) |
NODE_ENV | "production" switches the Console to its production posture |
Console operator rows are not stored in .oke/console.sqlite. With DATABASE_URL (or
OKE_STORE_SQL_URL) they live in Postgres schema oke_console. Without a Postgres URL,
Console uses PGlite under .oke/console-pg for local reopen durability.
Troubleshooting
Run oke dev (not a bare bun entry) so Compose posture sets OKE_DOCKER=1 and writes
connection URLs. Confirm images pins exist in Configuration.
Built-in vault needs OKE_VAULT_MASTER_KEY (or oke vault unseal). See
Vault.
Operator rows need DATABASE_URL or OKE_STORE_SQL_URL (schema oke_console). Without Postgres,
Console uses PGlite under .oke/console-pg.
Learn more
- Configuration — the declarative side of the same knobs
- Vault — how
OKE_VAULT_*gets minted on first boot - CLI — which commands write these for you
- Security —
OKE_CONSOLE_SECRET