Skip to content
open-ismsDocs

Search documentation

Find a page by title or topic

Configuration

Every environment variable, what breaks without it, and which two are mandatory.

Configuration is one .env file next to compose.yaml. Two variables are needed to boot, seven for an instance a human can actually use, and the rest each unlock or harden exactly one thing.

.env.self-host.example is the annotated version of everything below and is the file you copy. This page is the reference.

Required to start at all#

Startup validates the environment with Zod and refuses to run on a bad value, naming the variable in the error.

VariableNotes
DATABASE_URLPostgres connection string. The compose file builds it for you from POSTGRES_PASSWORD.
AUTH_SECRETMinimum 32 characters. openssl rand -base64 32. Anything shorter fails startup.

Required for a usable instance#

VariableWhat breaks without it
AUTH_URLEvery login. Auth.js derives its cookie name from this URL's scheme, so behind TLS with an http:// value set the middleware looks for a cookie that was never written. Set it to the URL your users type.
NEXT_PUBLIC_APP_URLLinks in outgoing email and canonical URLs point at nisd2.eu instead of you.
RESEND_API_KEY and RESEND_FROM_EMAILRegistration. Sign-up verifies the address with a one-time code, and with no key the send path logs a warning and returns success, so the flow looks fine and the code never arrives. Google OAuth is the alternative.
ERASURE_EMAIL_HASH_SALTGDPR erasure, which throws in production rather than fall back to a committed constant. Everything else works until someone requests erasure.

Storage#

VariableNotes
AWS_S3_BUCKETBucket for evidence files. With the minio profile a one-shot container creates it on first start.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYCredentials. Under the minio profile these are also MinIO's root user and password; the secret needs at least 8 characters.
AWS_S3_REGIONDefaults to eu-north-1. Irrelevant for MinIO, required for AWS.
AWS_S3_ENDPOINTThe address the browser uses. Setting it switches the S3 client to path-style URLs and rewrites the CSP so browser uploads are allowed.
AWS_S3_INTERNAL_ENDPOINTThe address the server uses, when it differs. Falls back to AWS_S3_ENDPOINT. Set with bundled MinIO, unset on AWS.
MINIO_KMS_KEYBundled MinIO only, and mandatory there: every upload sends x-amz-server-side-encryption: AES256, which MinIO answers out of a KMS. Exactly 32 bytes of base64.

Why two endpoints, and what goes wrong with one: Evidence storage.

Optional, one feature each#

VariableWithout it
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRETNo "Sign in with Google". Email and password still works.
XAI_API_KEYThe AI prefill button returns an error instead of filling the form. Manual entry is unaffected.
RAPIDAPI_KEYCompany lookup in the applicability wizard falls back to typing the details in.
CRON_SECRETThe deadline and course-reminder endpoints have no bearer token to check. Leave those jobs unscheduled.
PLATFORM_ADMIN_EMAILSNo cross-tenant /platform-admin tier. Most single-organisation installs want this unset.
SUPPORT_EMAIL, NEWSLETTER_REPLY_TOContact addresses fall back to placeholder values.
RESEND_FROM_EMAIL_NEWSNewsletter sends from RESEND_FROM_EMAIL instead of its own mailbox.
ANALYTICS_SCRIPT_URL, ANALYTICS_WEBSITE_IDNo analytics tag, which is the default. Both are required together, and the CSP allows the script's origin only when the URL is set. Nothing is reported to this project either way.
CAL_LINKThe booking UI is not rendered at all. Empty by default on purpose: a self-hosted instance must not embed someone else's calendar.
DISABLE_EMAIL=1Silences all outbound email. Useful for a staging copy of production data.
CSP_UPGRADE_INSECURE=1Set this only once you are HTTPS-only with a real certificate. It turns on HSTS with a two-year max-age, which pins HTTPS for that hostname the moment anyone visits over TLS.

The compose file, not the app#

These are read by the stack rather than by the application, and several have no effect unless their profile is on.

VariablePurpose
OPEN_ISMS_VERSIONWhich image tag runs. stable, or an exact version to pin and to roll back.
COMPOSE_REVISIONWhich revision of compose.yaml you are running. Reported at /api/health so a deployment cannot quietly drift from what a release expects.
COMPOSE_PROFILESWhich optional services run: minio, proxy, updater, backup.
POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DBThe bundled database. Only the password has no default.
APP_DOMAIN, STORAGE_DOMAINproxy profile. Both must resolve to this server before first start or the certificate order fails.
BACKUP_*backup profile. Target bucket, schedule, retention, and the GPG passphrase. See Backup and restore.
UPDATE_API_TOKENupdater profile. Authenticates a request to the updater over the internal network.
APP_BIND, APP_PORT, POSTGRES_BIND, POSTGRES_PORT, MINIO_BIND, MINIO_PORTHost bindings. Loopback by default.

Migration tunables#

Rarely touched, and set on the app container. The migrator takes a Postgres advisory lock so two containers starting at once cannot migrate the same database twice.

VariableDefaultMeaning
MIGRATE_LOCK_WAIT300sHow long to wait for another instance to finish migrating before giving up.
MIGRATE_LOCK_TIMEOUT10sCeiling on how long a single statement waits for its lock. A DDL statement blocked by a long-running query fails the migration instead of blocking startup forever.
MIGRATE_STATEMENT_TIMEOUT600sCeiling on a single statement inside a migration.

Declared but not implemented#

UPDATE_MODE is carried through .env and the compose file, and no application code reads it. Setting it to notify does nothing: the instance makes no outbound update request and nothing appears in the admin area. It is documented here because the variable exists and would otherwise look broken rather than unbuilt. See Updating for how to check for new versions today.

Development-only switches#

Present for local work and inert in the published image, which runs with NODE_ENV=production.

VariableEffect
ENABLE_DEV_AUTH=trueAdds a password-less "Dev Login" provider. Guarded by a NODE_ENV !== "production" check as well as the variable, so it cannot be turned on in a released image.
ENABLE_EMAIL_IN_DEV=trueSends real email from a development machine, which is otherwise hard-blocked.
SKIP_ENV_VALIDATION=1Skips the Zod check. For build steps that have no database, never for a running instance.