Operations

Configuration

Every environment variable, grouped by what it turns on, and how each app reads them.

All apps read one root .env in development (Turborepo passes it through; the API's ConfigModule also reads ../../.env). .env.example is the reference. New variables must also be added to turbo.json's globalEnv, to the Dockerfiles that need them, and to the self-hosting files (code standard 11).

Core

VariableMeaning
DATABASE_URLPostgres
S3_ENDPOINT, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKETThe bucket holding logs, assets, LFS, attachments, shards
BETTER_AUTH_SECRETSigns sessions and LFS tokens. Changing it signs everyone out
BETTER_AUTH_URLThe API's public origin; also the clone URL's origin
WEB_APP_URL, NEXT_PUBLIC_WEB_APP_URLThe web app's origin
NEXT_PUBLIC_API_URL, INTERNAL_API_URLThe API as the browser and as the Next server reach it
AUTH_TRUSTED_ORIGINS, AUTH_COOKIE_DOMAINCORS and cookie scope across web and API subdomains
API_PORT / PORTPort (PaaS platforms inject PORT)

Features, each off until set

VariableTurns on
GIT_SSH_HOST_KEY, GIT_SSH_PORT, NEXT_PUBLIC_SSH_CLONE_HOSTThe SSH transport
ZOEKT_URLCode search
MAIL_* or EMAIL_PROXY + EMAIL_PROXY_SECRET, EMAIL_SENDEREmail
EMAIL_VERIFICATION_ENABLEDRequiring verified addresses at sign-up
DELIVERY_EMAIL=queueThread emails through apps/delivery instead of inline
WEBHOOK_SECRET_KEY, WEBHOOK_ALLOW_PRIVATE_NETWORKS, WEBHOOK_HOST_CONCURRENCYWebhooks
COMMIT_SIGNING_KEYSigning commits Ghost writes
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, NEXT_PUBLIC_GITHUB_CLIENT_IDGitHub sign-in, required for imports
IMPORTER_URL, IMPORTER_SECRETGitHub imports
OTEL_EXPORTER_OTLP_ENDPOINT, PYROSCOPE_SERVER_ADDRESSTraces, metrics, profiles

Limits, unlimited until set

STORAGE_QUOTA_BYTES, FORK_STORAGE_QUOTA_BYTES, LFS_STORAGE_QUOTA_BYTES, ASSET_STORAGE_QUOTA_BYTES, RELEASE_ASSET_MAX_BYTES, PULL_REF_MAX_BYTES, PULL_REF_UNMERGED_MAX_BYTES. They accept bytes or units (1gb); a value that does not parse stops the API at boot, rather than silently meaning unlimited.

Build-time vs run-time

NEXT_PUBLIC_* variables are inlined into the browser bundle at build time. Changing one needs a rebuild of the web (or docs) image, not a restart. Dockerfiles take them as build arguments for that reason.

Check yourself

You change NEXT_PUBLIC_API_URL on a deployed web service and restart it. The browser still calls the old origin. Why?

On this page