Brain reads configuration from process.env via @nestjs/config and a few direct lookups
(apps/brain/src/main.ts, apps/brain/src/common/runtime/stage.ts,
apps/brain/src/config/queue.config.ts). The BRAIN_*-prefixed variables in
.env.example are mapped onto the unprefixed names that the service actually reads
in docker-compose.yml. On Railway the same mapping happens via the service env config.
The canonical .env.example is at the repo root.
| Var |
Required |
Default |
Source |
Purpose |
BRAIN_STAGE |
yes |
development |
.env.example, Railway |
Resolved by getBrainStage() to production/staging/sandbox/development; PR previews containing -pr- map to sandbox. |
RAILWAY_ENVIRONMENT_NAME |
platform |
— |
Railway runtime |
Stage fallback when BRAIN_STAGE is unset. |
NODE_ENV |
yes |
production (compose) |
docker-compose.yml, Railway |
Final stage fallback. |
PORT |
yes |
3000 |
docker-compose.yml, main.ts |
HTTP listen port; main.ts binds to IPv6 dual-stack ::. |
BRAIN_HTTP_PORT |
dev |
3000 |
.env.example |
Local override only; service still reads PORT. |
| Var |
Required |
Default |
Source |
Purpose |
DATABASE_URL |
yes |
— |
prisma/schema.prisma, Railway |
Pooled Prisma connection (Neon pgbouncer in prod). |
DIRECT_DATABASE_URL |
yes (migrations) |
falls back to DATABASE_URL |
prisma/schema.prisma, docker-compose.yml |
Direct (non-pooled) connection for prisma migrate deploy. |
BRAIN_DATABASE_URL |
dev |
— |
.env.example |
Mapped onto DATABASE_URL in compose. |
BRAIN_DIRECT_DATABASE_URL |
optional locally, required with pooled Neon |
falls back to BRAIN_DATABASE_URL |
.env.example, docker-compose.yml |
Mapped onto DIRECT_DATABASE_URL in compose. Set it when BRAIN_DATABASE_URL uses a pooler. |
DATABASE_REPLICA_URL |
no |
empty (every query on the primary) |
Railway (Neon read replica, pooled endpoint) |
Allowlisted read-only routes read this replica; everything else stays on the primary. Inherits DATABASE_URL’s ?schema= when it has none; its pool is sized by its own connection_limit, not BRAIN_DB_POOL_*. See Neon read replicas (withReadReplica in apps/brain/src/modules/application/prisma/services/prisma.service.ts). |
BRAIN_DATABASE_REPLICA_URL |
dev |
empty |
.env.example, docker-compose.yml |
Mapped onto DATABASE_REPLICA_URL in compose. |
Brain owns the fennec schema in the shared sirloin DB. See Data Model.
| Var |
Required |
Default |
Source |
Purpose |
REDIS_HOST |
yes |
localhost |
apps/brain/src/config/queue.config.ts |
BullMQ connection host. |
REDIS_PORT |
yes |
6379 |
queue.config.ts |
BullMQ connection port. |
REDIS_PASSWORD |
optional |
— |
queue.config.ts |
Auth where Redis is password-protected. |
family: 0 is set so dual-stack IPv4/IPv6 resolution works on Railway’s private network.
| Var |
Required |
Default |
Source |
Purpose |
CLERK_PUBLISHABLE_KEY |
yes |
— |
Clerk dashboard |
Frontend Clerk identifier. |
CLERK_SECRET_KEY |
yes |
— |
Clerk dashboard |
Server-side token verification (@clerk/backend). |
AUTHORIZED_KEYS |
yes |
— |
Generated; rotated per-stage |
Comma-separated list of API keys accepted by @ApiKeyRoute() endpoints. See Auth Model “API key scopes”. |
BRAIN_CLERK_PUBLISHABLE_KEY / BRAIN_CLERK_SECRET_KEY / BRAIN_AUTHORIZED_KEYS |
dev |
— |
.env.example |
Mapped onto the unprefixed names by compose. |
FRONTEND_URL |
yes |
— |
app.module.ts |
Used for CORS / redirect validation. |
BRAIN_API_PUBLIC_URL |
optional |
http://localhost:9970 |
.env.example |
Local docs; clients consume the Railway URL in non-dev. |
| Var |
Required |
Default |
Purpose |
S3_BUCKET_NAME |
yes |
— |
Tenderloin bucket (R2) for media. |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY |
yes |
— |
R2 credentials. |
AWS_S3_APIREGION |
yes |
auto |
R2 region. |
AWS_S3_APIURL |
yes |
— |
R2 endpoint (e.g. https://<accountid>.r2.cloudflarestorage.com). |
BRAIN_PUBLIC_BUCKET_URL |
yes |
— |
Public CDN domain for downloads. |
| Var |
Required |
Default |
Purpose |
ROUND_HOST |
yes |
round:8080 |
gRPC target for round (embeddings, face). |
BRAIN_ROUND_HOST |
dev |
round:8080 |
Mapped onto ROUND_HOST. |
BRAIN_SIRLOIN_JOBS_SHADOW_ENABLED |
no |
false |
FOXY-1038 PoC: shadow-enqueue media completions into Sirloin’s job queue via jobs.v1.JobService (same host/token as the character-control dial-back). Fire-and-forget beside the webhook; off by default, operators choose where to enable it. |
All optional individually but at least the providers used by enabled flows must be set.
| Var |
Provider |
BRAIN_RUNPOD_TOKEN |
RunPod inference. |
BRAIN_FAL_AI_KEY |
Fal inference. |
BRAIN_FAL_ADMIN_KEY |
Fal workspace usage and spend synchronization. |
BRAIN_SPEND_SYNC_LOOKBACK_DAYS |
Number of previous UTC days synchronized with the current day. Defaults to 7. |
BRAIN_GOOGLE_AI_API_KEY |
Google AI Studio. |
BRAIN_GOOGLE_CLOUD_SERVICE_ACCOUNT_KEY |
Google Vertex AI service account JSON. |
BRAIN_GOOGLE_CLOUD_PROJECT_ID, BRAIN_GOOGLE_CLOUD_LOCATION |
Vertex region. |
BRAIN_KLING_AI_API_KEY, BRAIN_KLING_AI_API_SECRET |
Kling AI. |
BRAIN_WAVESPEED_API_KEY |
Wavespeed video. |
BRAIN_ATLASCLOUD_API_KEY |
AtlasCloud inference (Seedream, Seedance). |
BRAIN_HF_TOKEN |
Hugging Face. |
BRAIN_XAI_API_KEY |
xAI / Grok. |
BRAIN_OPENROUTER_API_KEY |
OpenRouter (language extraction). |
Before enabling Fal spend synchronization, confirm that BRAIN_FAL_ADMIN_KEY
belongs to the production Fal workspace. Fal does not return a workspace
identifier with usage data. Brain skips a window when every returned bucket is
empty or zero. This guard prevents an empty-scope key from erasing history, but
it cannot detect non-zero usage from the wrong workspace. It also preserves a
stale non-zero value for a genuinely all-zero window until manual
reconciliation.
| Var |
Purpose |
BRAIN_HIVE_CELEBRITY_RECOGNITION_API_KEY |
Hive celebrity check. |
BRAIN_HIVE_VISUAL_MODERATION_API_KEY |
Hive visual moderation. |
BRAIN_HIVE_DEMOGRAPHICS_API_KEY |
Hive demographics. |
| Var |
Purpose |
BRAIN_VI_GENERATOR_URL |
Outbound base URL. |
BRAIN_VI_GENERATOR_API_KEY |
API key. |
BRAIN_VI_GENERATOR_CF_ACCESS_CLIENT_ID / _SECRET |
Cloudflare Access service token. |
| Var |
Purpose |
BRAIN_GEMINI_IMAGE_SIGNATURE_KEY |
HMAC for signed Gemini outputs. |
BRAIN_FENNEC_IMAGE_SIGNATURE_KEY |
HMAC for signed fennec image URLs. |
| Var |
Required |
Purpose |
BRAIN_OTEL_URL |
yes (prod) |
Axiom OTEL endpoint. |
BRAIN_OTEL_METRICS_HEADERS |
yes (prod) |
authorization=Bearer xaat-...,x-axiom-dataset=.... |
BRAIN_OTEL_TRACES_LOGS_HEADERS |
yes (prod) |
Same shape, traces+logs dataset. |
BRAIN_OTEL_LOCAL_MOCK |
no |
Local-only: bypasses the production/staging gate and, only when BRAIN_OTEL_URL is unset, defaults the URL/headers to an in-process throwaway collector — it never overrides an explicit BRAIN_OTEL_URL. See Brain Local Development. |
See Observability.
- TODO(@pawel): Validate which of the AI provider keys are required per stage vs. lazily resolved at first use.
- TODO(@pawel): Confirm
family: 0 Redis behavior on Upstash vs. self-hosted Redis (set in apps/brain/src/config/queue.config.ts:11).