Environment Variables
Required
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string. Pooled URL for serverless. |
NEXTAUTH_SECRET | 32-byte random secret for JWT signing. openssl rand -base64 32. |
NEXTAUTH_URL | Public origin (https://cms.example.com). |
ADMIN_EMAIL, ADMIN_PASSWORD | Bootstrap admin user. Used by pnpm db:seed. |
SUPABASE_URL | Supabase project URL. |
SUPABASE_SERVICE_KEY | Server-side service role key. |
SUPABASE_STORAGE_BUCKET | Bucket name. Auto-created (public) on first upload if it doesn't exist. |
Recommended
| Variable | Purpose |
|---|---|
CRON_SECRET | Bearer token for /api/cron/* handlers. Required in production. |
CRON_SCHEDULED_PUBLISH_INTERVAL_MIN | Subsample the hourly scheduled-publish cron — only run work every N minutes so Neon can scale to zero between ticks. Recommended 15. |
CRON_WEBHOOK_RETRY_INTERVAL_MIN | Same subsampling for the webhook-retry cron. Recommended 15. |
KRIOS_DATA_REGION | Informational region label surfaced via X-Krios-Data-Region header. |
DATABASE_URL_UNPOOLED | Reserved / not currently wired — the Prisma schema declares no directUrl, so migrations run against DATABASE_URL. Keep it set for forward-compatibility, but it isn't read today. |
Optional
| Variable | Purpose |
|---|---|
KRIOS_DATABASE_REGION | Display-only, e.g. Neon (us-east-2) for Settings → Security. |
KRIOS_STORAGE_REGION | Display-only, e.g. Supabase (us-east-1). |
STORAGE_PROVIDER | supabase (default) or local. |
SEARCH_PROVIDER | postgres (default) or meilisearch. |
MEILI_HOST | Meilisearch endpoint (when SEARCH_PROVIDER=meilisearch). The functional name read by the search provider. |
MEILI_API_KEY | Meilisearch admin key. The functional name read by the search provider. |
KRIOS_TENANT_DB_KEY | 32+ char key for AES-256-GCM encryption of per-tenant DB URLs. |
CORS_ALLOWED_ORIGINS | Comma-separated global CORS allow-list fallback (used when a project/site has no specific config). |
RATE_LIMIT_DELIVERY | Override the project-level delivery rate limit. |
RATE_LIMIT_MANAGEMENT | Override the project-level management rate limit. |
The codebase is inconsistent here: the search provider reads MEILI_HOST / MEILI_API_KEY (the functional pair, above), while .env.example and the /api/health probe read MEILISEARCH_URL / MEILISEARCH_API_KEY. Set MEILI_HOST / MEILI_API_KEY to make search work; also set the MEILISEARCH_* pair if you want the health check to report Meilisearch correctly.
Other optional vars: MAX_FILE_SIZE_MB (upload size cap), LOG_LEVEL (structured-log verbosity), and Sentry (SENTRY_DSN, NEXT_PUBLIC_SENTRY_DSN). WEBHOOK_DEFAULT_TIMEOUT_MS is not read by code — the webhook delivery timeout is a hardcoded 5s and is not configurable.
Local dev .env
DATABASE_URL="postgresql://..."
NEXTAUTH_SECRET="$(openssl rand -base64 32)"
NEXTAUTH_URL="http://localhost:3000"
ADMIN_EMAIL="you@example.com"
ADMIN_PASSWORD="…"
SUPABASE_URL="https://….supabase.co"
SUPABASE_SERVICE_KEY="…"
SUPABASE_STORAGE_BUCKET="krios-media"
Production extras
CRON_SECRET="$(openssl rand -base64 32)"
CRON_SCHEDULED_PUBLISH_INTERVAL_MIN="15" # subsample the hourly cron so Neon can idle
CRON_WEBHOOK_RETRY_INTERVAL_MIN="15"
KRIOS_DATA_REGION="us-east"
KRIOS_DATABASE_REGION="Neon (us-east-2)"
KRIOS_STORAGE_REGION="Supabase (us-east-1)"
KRIOS_TENANT_DB_KEY="<32+ char random>" # only when using V3 physical isolation
SEARCH_PROVIDER="meilisearch" # only when using Meilisearch
MEILI_HOST="https://meili.example.com"
MEILI_API_KEY="…"
Loading in Vercel
Settings → Environment Variables. Set each variable for Production, Preview, and Development as appropriate. The same variable can have different values per environment.
Sensitive values (*_SECRET, *_KEY, *_PASSWORD) should be marked as encrypted in the Vercel UI — Vercel encrypts them at rest and surfaces them only to the running function.
Loading in self-hosted
Source from your secrets manager into the process environment before pnpm start. Don't commit .env.production to source control. systemd services should use EnvironmentFile= pointing at a root-only file, or pull from Vault / AWS Secrets Manager / Doppler at boot.