Configuration is a contract, not a bag of environment variables.
`lib/env.js` parses, validates, defaults, and groups runtime settings. `.env.example` documents the available surface without containing deployable secrets.
Configuration groups
HTTP runtime
- NODE_ENV
- PORT
- PUBLIC_APP_ORIGIN
- TRUST_PROXY
- CORS origins
- cookie names
- log level
Supabase
- project URL
- publishable/anon key
- service role key
- database URL
- password reset origin
Cloudflare R2 and playback
- account and bucket
- access keys
- public media origin
- playback gateway
- signing and proxy secrets
Stripe and licensing
- secret key
- webhook secret
- price IDs
- trial days
- success/cancel URLs
- AppSumo settings
Rooms and realtime
- meeting token secret
- duration limits
- TURN
- LiveKit
- SFU/egress
- host/token policy
STT and translation
- STT routing
- Canary
- self-hosted Whisper
- NVIDIA NIM
- language allowlists
- concurrency limits
Background processing
- enable switches
- poll intervals
- batch size
- leases
- retry limits
- cleanup and summary cadence
Domains and operations
- domain feature and DNS targets
- Caddy ask token
- email provider
- Redis
- metrics
- Superadmin policy
Configuration precedence
The runtime reads process environment variables. Local scripts may load .env and an explicitly selected overlay. Deployment environments provide production or staging values outside the release archive. Never rely on a developer’s untracked local file as release configuration.
Recommended separation:
.env.example: names, safe examples, and comments..env: local developer configuration only.deploy/meet-only/meet-only.env.example: safe meeting-only template.- VPS/shared environment: production or staging secrets and provider endpoints.
- GitHub Actions secrets: deployment transport and workflow credentials.
Modes
Full SaaS
Requires valid Supabase, database, R2, Stripe, session, meeting, and provider configuration for the enabled features. npm run ops:full-saas-preflight verifies the broader production contract.
Meet-only
MEET_ONLY_MODE=true disables account/workspace product dependencies and supplies safe local fallbacks for unrelated R2/Stripe settings. It is designed for a public meeting stack where Supabase persistence may be omitted. A non-empty placeholder database URL can still trigger an unwanted connection attempt, so meet-only configuration must leave disabled dependencies genuinely empty.
Staging
Staging uses a separate VPS application path, port, health origin, environment, and deploy workflow. Provider callbacks, domains, buckets, and database projects must not accidentally point at production unless the specific integration is intentionally shared.
Secrets and public configuration
Safe browser configuration is generated through /app-config.js and public API responses. Only public origins, feature flags, publishable client settings, and non-secret provider capabilities belong there.
Never expose:
- Supabase service-role or secret keys.
- Database connection strings.
- R2 access-key secrets.
- Stripe secret or webhook signing secrets.
- Meeting, playback, Caddy ask, TURN shared, email bearer, or SCIM token secrets.
- NVIDIA, OpenAI, or other provider API keys.
Validation workflow
npm run ops:preflight
npm run ops:full-saas-preflight
npm run ops:meet-dependency-gate
npm run security:secretsChoose the check that matches the intended mode. A meet-only preflight should not pretend to validate a full paid recording workspace, and a full SaaS release should not pass only because disabled-provider fallbacks exist.
Provider failure behavior
- Missing required production secrets fail startup.
- Optional providers advertise unavailable status and keep the unrelated product usable.
- Translation errors are surfaced rather than routed to an undeclared provider.
- STT can follow explicit fallback rules for device capability, language support, hosted failure, and self-hosted availability.
- Redis failure can fall back to memory where allowed, but distributed rate-limit expectations must be adjusted.
- Email
logmode is for local development; production delivery requires the configured HTTPS provider bridge.