Environment Variables

Every environment variable thunder-core reads, plus database-backed env vars resolved at runtime.

thunder-core reads the variables below. Set them in .env, or store them at runtime in the envs collection (see Database-backed Env Vars).

The authoritative list is whatever the code reads. If in doubt, grep for Env.get / Env.list / Env.number / Env.enabled / Env.params across lib/, utils/, routes/, and hooks/.

Required

BASE_URL=http://localhost:8000        # Public base URL; used by better-auth & the OAuth2 issuer
SECRET_KEY=<random-strong-secret>     # Signing secret for sessions and OAuth2 JWTs
BETTER_AUTH_CAPABILITIES=email,signup # Comma list enabling auth features (see below)

BETTER_AUTH_CAPABILITIES toggles auth features (see lib/auth.ts):

CapabilityEffect
signupAllow new user creation
emailEnable email + password auth
magicLinkEnable magic-link sign up / sign in
githubEnable the GitHub social provider (requires GITHUB_* vars)
multiSessionAllow multiple concurrent sessions per user

Auth / Session (optional)

BETTER_AUTH_TRUSTED_ORIGIN=http://localhost:3000  # Comma list of trusted origins
BETTER_AUTH_TRUST_DEVICE_DAYS=30                   # 2FA trust-device window (default 30)
BETTER_AUTH_MAX_MULTI_SESSIONS=5                   # Max sessions when multiSession is enabled (default 5)
GITHUB_CLIENT_ID=...                               # Required only if the "github" capability is on
GITHUB_CLIENT_SECRET=...

Branding

Served by the auth branding endpoint:

APP_DISPLAY_NAME=My App         # Required for the branding endpoint
APP_DESCRIPTION=...             # Optional
APP_LOGO=https://.../logo.png   # Optional
APP_HOMEPAGE_URL=https://...    # Optional
APP_THEME=primary:#000&bg:#fff  # Parsed via Env.params() into a key/value record

Email (SMTP)

Used by the Mailer:

SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USERNAME=...
SMTP_PASSWORD=...
SMTP_SENDER=no-reply@example.com
SMTP_SENDER_NAME=My App

ImageKit

IMAGEKIT_PRIVATE_KEY=private_...
IMAGEKIT_PUBLIC_KEY=public_...

RBAC Behavior

RBAC_NO_CASCADE=false  # If true, a tenant member's role does NOT cascade from the parent inviter

Database-backed Env Vars

The essentials hook (hooks/essentials.ts) installs Env.onGetFailed, so any env var not found in the process environment is looked up in the envs MongoDB collection ({ key, value }).

This lets you manage secrets/config at runtime through the envs CRUD route instead of redeploying. The same hook also handles CORS (preflight + response headers, and allows the X-TENANT-ID header).

Because of this fallback, you can ship with only DATABASE_URL and SECRET_KEY in .env and store the rest in the database - useful for rotating secrets without a redeploy.


On this page