Configuration
Configuration is entirely environment-driven. .env.example in the repository root is the
authoritative list; the tables below cover the variables that matter most for a self-hosted instance.
Run-time variables
Section titled “Run-time variables”These must be present when the app starts.
| Variable | Description | Required | Default |
|---|---|---|---|
DATABASE_URL |
Database URL with credentials. If you use a connection pooler, point this at the pooler. | required | postgresql://unicorn_user:magical_password@database:5432/calendso |
NEXT_PUBLIC_WEBAPP_URL |
Base URL of the site. The image ships a placeholder in its statically built files, which is rewritten to this value the first time the container starts. | optional | http://localhost:3000 |
NEXTAUTH_URL |
Location of the auth server. Defaults to the flexcal instance itself. | optional | {NEXT_PUBLIC_WEBAPP_URL}/api/auth |
NEXTAUTH_SECRET |
Cookie encryption key. Must match the build-time value. Generate with openssl rand -base64 32. |
required | secret |
CALENDSO_ENCRYPTION_KEY |
Authentication encryption key, 32 bytes for AES256. Must match the build-time value. Generate with openssl rand -base64 24. |
required | secret |
SKIP_DB_MIGRATIONS |
Set to 1 to stop the container applying migrations on start. Leave unset for Docker Compose, which has nowhere else to run them. Set it when the deployment migrates once per release, otherwise every replica races the others. |
optional | unset |
SKIP_APP_STORE_SEED |
Set to 1 to stop the container seeding the app store on start. Same reasoning as SKIP_DB_MIGRATIONS; the seed costs roughly 8s of every pod’s startup. |
optional | unset |
NEXT_PUBLIC_VAPID_PUBLIC_KEY |
Web push public key, generated with npx web-push generate-vapid-keys. |
required for push | unset |
VAPID_PRIVATE_KEY |
Web push private key from the same key pair. | required for push | unset |
DATABASE_SCHEMA |
Schema that Prisma resolves unqualified objects against. Appended to DATABASE_URL and DATABASE_DIRECT_URL as schema= when neither already names one, so an explicit schema= in the URL always wins. Only change this if the deployment genuinely keeps flexcal’s tables outside public. |
optional | public |
A note on the database schema
Section titled “A note on the database schema”Prisma only issues SET search_path when the connection URL carries a schema= argument. Without
one, the session keeps the PostgreSQL default of "$user", public, so on a deployment where the
database role owns a schema of the same name, unqualified CREATE TABLE / CREATE TYPE in a
migration lands in that role schema rather than in public. Prisma then looks in public, finds
nothing, and the application keeps working only by search_path accident: a connection using a
different role or search_path breaks.
Setups where the role owns a same-named schema include Crunchy PostgreSQL Operator with
autoCreateUserSchema, Supabase, and any database where someone created a schema named after the
login role.
The container handles this for you: scripts/start.sh pins the schema before touching the database.
Databases that already have stranded objects are repaired by the
20260818120000_relocate_shadow_schema_objects migration, which moves them back into public. It
reports a warning and changes nothing where public already holds an object of the same name.
Build-time variables
Section titled “Build-time variables”These are baked in when the image or the app is built. Changing them means rebuilding.
| Variable | Description | Required | Default |
|---|---|---|---|
DATABASE_URL |
Only needs to be parseable at build time; no connection is made. | required | postgresql://unicorn_user:magical_password@database:5432/calendso |
MAX_OLD_SPACE_SIZE |
Node.js heap size for the build, in MB. | optional | 6144 |
NEXTAUTH_SECRET |
Cookie encryption key. | required | secret |
CALENDSO_ENCRYPTION_KEY |
Authentication encryption key. | required | secret |
NEXT_PUBLIC_WEBAPP_URL |
Default base URL for the built image; a deployment overrides it with the run-time variable of the same name. | optional | http://localhost:3000 |
NEXT_PUBLIC_WEBSITE_TERMS_URL |
Custom URL for the terms and conditions page. | optional | |
NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL |
Custom URL for the privacy policy page. | optional | |
NEXT_PUBLIC_CALCOM_VERSION |
Version string rendered in the footer; unset renders dev. |
optional | |
CSP_POLICY |
Content Security Policy mode, see below. | optional | |
CALCOM_TELEMETRY_DISABLED |
Set to 1 to disable anonymous usage telemetry. |
optional |
Content Security Policy
Section titled “Content Security Policy”Set CSP_POLICY="non-strict" to enable Strict CSP with the exception of
unsafe-inline in style-src. Custom changes to an instance may need adjusting to stay CSP-compatible.
Strict CSP is currently enforced only on the login page. Other server-rendered pages run it in report-only mode to surface problems. Statically generated pages are not covered yet.
Logging
Section titled “Logging”NEXT_PUBLIC_LOGGER_LEVEL controls verbosity for all tRPC queries and mutations. The level you set
is the minimum that gets logged:
| Value | Level |
|---|---|
0 |
silly |
1 |
trace |
2 |
debug |
3 |
info |
4 |
warn |
5 |
error |
6 |
fatal |
echo 'NEXT_PUBLIC_LOGGER_LEVEL=3' >> .envApp credentials
Section titled “App credentials”Third-party integrations read their credentials from .env and .env.appStore.
See the Apps section for the per-provider setup.