Configuration
This page lists every setting the API and the standalone worker read, generated from the API's own schema. You can set each one as an environment variable or in a file inside the container, /app/config/local.toml or /app/config/local.json. Environment variables override the file.
An environment variable's name is the setting's path in upper case, with underscores between words and between path parts: jwt.superAdminPredicate becomes JWT_SUPER_ADMIN_PREDICATE. A list takes 1 variable per entry, numbered from 0, such as JWT_ALGORITHMS_0. An empty variable still counts as set. The Setting column shows the variable's name on its second line.
Durations use ISO 8601 notation, such as PT30S or P7D. Intervals accept time units only: PT24H works, P1D does not.
The web app has settings of its own, which Sign-in provider lists.
general
| Setting | Type | Default | Description |
|---|---|---|---|
portPORT | integer, 1 to 65535 | 3000 | The port the API listens on. |
log
Logging to standard output: JSON lines when NODE_ENV is production, readable text otherwise.
| Setting | Type | Default | Description |
|---|---|---|---|
log.levelLOG_LEVEL | one of trace, debug, info, warn, error, fatal | info |
postgres
The PostgreSQL database.
| Setting | Type | Default | Description |
|---|---|---|---|
postgres.hostnamePOSTGRES_HOSTNAME | string | Required | |
postgres.portPOSTGRES_PORT | integer, 1 to 65535 | Defaults to the PostgreSQL port, 5432. | |
postgres.databasePOSTGRES_DATABASE | string | Required | |
postgres.usernamePOSTGRES_USERNAME | string | Required | |
postgres.passwordPOSTGRES_PASSWORD | string | Required | |
postgres.poolSizePOSTGRES_POOL_SIZE | integer, at least 2 | 10 | The most connections the pool opens in each process; a process running jobs holds one more outside it, to hear about new jobs. At least 2, since booting holds a lock on one connection while migrating on another, so a pool of one cannot boot. A standalone worker needs its worker.runtime.concurrency plus 2. |
postgres.connectionTimeoutPOSTGRES_CONNECTION_TIMEOUT | integer, at least 1 | 10000 | Milliseconds to wait for a database connection, both when opening one and when waiting for a free one from the pool. |
jwt
Verifying the access tokens the sign-in provider issues.
| Setting | Type | Default | Description |
|---|---|---|---|
jwt.issuerJWT_ISSUER | string | Required | The OpenID Connect issuer. Its discovery document is fetched at startup, so the API does not start while the issuer is unreachable. |
jwt.audienceJWT_AUDIENCE | string | Required | The audience access tokens must carry. |
jwt.algorithmsJWT_ALGORITHMS_<n> | list of one of RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA | ["RS256"] | The signature algorithms accepted on access tokens. Asymmetric only: tokens are verified against the issuer's published keys, so shared-secret HS256 and its siblings are not supported. |
jwt.superAdminPredicateJWT_SUPER_ADMIN_PREDICATE | string | Required | A JMESPath expression evaluated against the verified token; a truthy result makes the caller a super admin. Guard a claim that may be absent, as in the second example. An expression that fails to evaluate counts as false. Examples: sub == 'a' || sub == 'b', contains(realm_access.roles || `[]`, 'superadmin') |
jwt.integrationPredicateJWT_INTEGRATION_PREDICATE | string | Required | A JMESPath expression evaluated against the verified token; a truthy result makes the caller the trusted integration that reads the published schedule. Written like superAdminPredicate. Examples: sub == 'integration' |
jwt.debugJWT_DEBUG | boolean | false | Puts the reason a token was rejected into the 401 response. For debugging only: it tells every client why verification failed. |
userInfo
Reading a person's name and email address from the sign-in provider's userinfo endpoint.
| Setting | Type | Default | Description |
|---|---|---|---|
userInfo.emailAddressPathUSER_INFO_EMAIL_ADDRESS_PATH | string | A JMESPath expression picking the email address out of the provider's userinfo response. Left unset, people enter their address themselves. Examples: email | |
userInfo.displayNamePathUSER_INFO_DISPLAY_NAME_PATH | string | A JMESPath expression picking the display name out of the provider's userinfo response. Left unset, people enter their name themselves. Examples: name, join(' ', [given_name, family_name][?@]) | |
userInfo.cacheTtlUSER_INFO_CACHE_TTL | ISO 8601 duration | PT5M | How long a userinfo response is reused. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
cors
Cross-origin requests from the web app.
| Setting | Type | Default | Description |
|---|---|---|---|
cors.originCORS_ORIGIN | string | Required | The web app's origin exactly as a browser sends it: lowercase scheme and host, plus the port only when it is not the default, with no path or trailing slash. Examples: https://eventail.example.com |
s3
The S3-compatible bucket holding uploads. Browsers upload to it directly, so it needs a CORS rule allowing POST from the web app's origin, and public images need a bucket policy.
| Setting | Type | Default | Description |
|---|---|---|---|
s3.bucketNameS3_BUCKET_NAME | string | Required | |
s3.maxFileSizeS3_MAX_FILE_SIZE | string | Required | The largest upload accepted, with a unit from B to TB. Examples: 10mb, 1.5GB |
s3.publicBaseUrlS3_PUBLIC_BASE_URL | URL | Required | The publicly reachable base URL of the bucket. Image URLs are this plus the object key. |
s3.client
Connecting to the S3-compatible object store.
| Setting | Type | Default | Description |
|---|---|---|---|
s3.client.endpointS3_CLIENT_ENDPOINT | string | Required | The store's URL. |
s3.client.regionS3_CLIENT_REGION | string | Falls back to AWS_REGION, then the region of the AWS profile in the shared config files, then EC2 instance metadata; AWS_DEFAULT_REGION is not read. Something has to set it even for stores without regions; us-east-1 works for those. | |
s3.client.forcePathStyleS3_CLIENT_FORCE_PATH_STYLE | boolean | Addresses the bucket as a path on the endpoint rather than as a subdomain. Most self-hosted stores need this. |
s3.client.credentials
Left unset, the AWS default credential chain applies, such as AWS_* environment variables or an instance role. An empty value counts as set.
| Setting | Type | Default | Description |
|---|---|---|---|
s3.client.credentials.accessKeyIdS3_CLIENT_CREDENTIALS_ACCESS_KEY_ID | string | Required | |
s3.client.credentials.secretAccessKeyS3_CLIENT_CREDENTIALS_SECRET_ACCESS_KEY | string | Required |
s3.requestHandler
Timeouts for each attempt at a request to the store. A stalling store is retried, so one request can take several times these.
| Setting | Type | Default | Description |
|---|---|---|---|
s3.requestHandler.connectionTimeoutS3_REQUEST_HANDLER_CONNECTION_TIMEOUT | integer, at least 1 | 3000 | Milliseconds to wait for a connection to the store. |
s3.requestHandler.socketTimeoutS3_REQUEST_HANDLER_SOCKET_TIMEOUT | integer, 1 to 5999 | 5000 | Milliseconds a request may go without data. Must stay below 6000, above which the client stops covering a stalled response body. |
frontend
The web app.
| Setting | Type | Default | Description |
|---|---|---|---|
frontend.baseUrlFRONTEND_BASE_URL | URL | Required | The web app's URL, used for the links in mails. |
worker
Background jobs and maintenance. The API runs a worker itself unless disableBuiltIn is set; standalone workers run the same image with ./worker.js.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.disableBuiltInWORKER_DISABLE_BUILT_IN | boolean | Stops the API process from running jobs itself. Set it when standalone workers run, and only then: without either, no jobs run and no mail goes out. |
worker.leader
Electing the one process that runs the maintenance tasks below, however many workers run.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.leader.electionIntervalWORKER_LEADER_ELECTION_INTERVAL | ISO 8601 duration | PT1M | How often a process that is not the leader tries to become it. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.leader.pollIntervalWORKER_LEADER_POLL_INTERVAL | ISO 8601 duration | PT1M | How often the leader checks that it still is. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.runtime
Claiming and running jobs.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.runtime.fallbackIntervalWORKER_RUNTIME_FALLBACK_INTERVAL | ISO 8601 duration | PT30S | How often to look for jobs without being notified of one, covering missed notifications. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.runtime.reconnectDelayWORKER_RUNTIME_RECONNECT_DELAY | ISO 8601 duration | PT5S | How long to wait before reconnecting after the database connection drops. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.runtime.drainTimeoutWORKER_RUNTIME_DRAIN_TIMEOUT | ISO 8601 duration | PT15S | How long shutting down waits for running jobs to finish. An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.runtime.maxAttemptsWORKER_RUNTIME_MAX_ATTEMPTS | integer, at least 1 | 25 | How often a failing job is tried before it is given up. |
worker.runtime.concurrencyWORKER_RUNTIME_CONCURRENCY | integer, at least 1 | 1 | Jobs a standalone worker runs at once; the built-in worker always runs one. Needs postgres.poolSize of at least this plus 2. |
worker.scheduler
Makes scheduled jobs and jobs due for a retry available.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.scheduler.intervalWORKER_SCHEDULER_INTERVAL | ISO 8601 duration | PT5S | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.scheduler.limitWORKER_SCHEDULER_LIMIT | integer, at least 1 | 1000 | Jobs handled per batch. |
worker.cleaner
Deletes finished jobs once their retention period, an ISO 8601 duration, has passed.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.cleaner.intervalWORKER_CLEANER_INTERVAL | ISO 8601 duration | PT30S | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.cleaner.canceledJobRetentionPeriodWORKER_CLEANER_CANCELED_JOB_RETENTION_PERIOD | ISO 8601 duration | PT24H | Examples: PT1H |
worker.cleaner.completedJobRetentionPeriodWORKER_CLEANER_COMPLETED_JOB_RETENTION_PERIOD | ISO 8601 duration | PT24H | Examples: PT1H |
worker.cleaner.discardedJobRetentionPeriodWORKER_CLEANER_DISCARDED_JOB_RETENTION_PERIOD | ISO 8601 duration | P7D | Examples: PT1H |
worker.inviteSweeper
Deletes expired invites.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.inviteSweeper.intervalWORKER_INVITE_SWEEPER_INTERVAL | ISO 8601 duration | PT1H | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.userSweeper
Deletes accounts nobody has used for the retention period, unless they host a session or belong to a team.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.userSweeper.intervalWORKER_USER_SWEEPER_INTERVAL | ISO 8601 duration | PT6H | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.userSweeper.retentionPeriodWORKER_USER_SWEEPER_RETENTION_PERIOD | ISO 8601 duration | P180D | How long an account may go without its owner opening the web app. An ISO 8601 duration. Examples: P365D |
worker.filePruner
Deletes objects in the bucket that nothing refers to anymore, and uploads that were never finished.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.filePruner.intervalWORKER_FILE_PRUNER_INTERVAL | ISO 8601 duration | PT24H | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.filePruner.minimumAgeWORKER_FILE_PRUNER_MINIMUM_AGE | ISO 8601 duration | PT24H | The least time an object stays unreferenced before it is deleted, counted from when the pruner first finds it so; unfinished uploads count from when they were uploaded. The deletion itself waits for the next run after that. An ISO 8601 duration. Examples: PT1H |
worker.rescuer
Makes a job that has been running longer than rescueAfter available again, taking its worker to be gone, or gives it up after worker.runtime.maxAttempts. A job still running then runs twice, so rescueAfter has to exceed the longest job.
| Setting | Type | Default | Description |
|---|---|---|---|
worker.rescuer.intervalWORKER_RESCUER_INTERVAL | ISO 8601 duration | PT30S | An ISO 8601 duration in time units only. Examples: PT30S, PT6H |
worker.rescuer.limitWORKER_RESCUER_LIMIT | integer, at least 1 | 1000 | Jobs handled per batch. |
worker.rescuer.rescueAfterWORKER_RESCUER_RESCUE_AFTER | ISO 8601 duration | PT1H | How long a job may run before it counts as stuck. An ISO 8601 duration. Examples: PT1H |
email
Sending mail.
| Setting | Type | Default | Description |
|---|---|---|---|
email.senderEMAIL_SENDER | email address | Required | The From address of every mail. |
email.confirmReminderCooldownEMAIL_CONFIRM_REMINDER_COOLDOWN | ISO 8601 duration | P3D | How long after one reminder to confirm a session the next may be sent. An ISO 8601 duration. Examples: PT1H |
email.smtp
The mail server, passed to nodemailer's SMTP transport; its documentation covers each option. Timeouts are in milliseconds.
| Setting | Type | Default | Description |
|---|---|---|---|
email.smtp.hostEMAIL_SMTP_HOST | string | ||
email.smtp.portEMAIL_SMTP_PORT | integer, 1 to 65535 | ||
email.smtp.authMethodEMAIL_SMTP_AUTH_METHOD | string | ||
email.smtp.secureEMAIL_SMTP_SECURE | boolean | Speaks TLS from the start. Unset, only port 465 does; elsewhere TLS depends on the server offering STARTTLS, unless requireTLS demands it or ignoreTLS skips it. | |
email.smtp.ignoreTLSEMAIL_SMTP_IGNORE_TLS | boolean | ||
email.smtp.requireTLSEMAIL_SMTP_REQUIRE_TLS | boolean | ||
email.smtp.opportunisticTLSEMAIL_SMTP_OPPORTUNISTIC_TLS | boolean | ||
email.smtp.nameEMAIL_SMTP_NAME | string | ||
email.smtp.localAddressEMAIL_SMTP_LOCAL_ADDRESS | string | ||
email.smtp.connectionTimeoutEMAIL_SMTP_CONNECTION_TIMEOUT | integer, at least 1 | ||
email.smtp.greetingTimeoutEMAIL_SMTP_GREETING_TIMEOUT | integer, at least 1 | ||
email.smtp.socketTimeoutEMAIL_SMTP_SOCKET_TIMEOUT | integer, at least 1 | ||
email.smtp.dnsTimeoutEMAIL_SMTP_DNS_TIMEOUT | integer, at least 1 | ||
email.smtp.poolEMAIL_SMTP_POOL | boolean | ||
email.smtp.maxConnectionsEMAIL_SMTP_MAX_CONNECTIONS | integer, at least 1 | ||
email.smtp.maxMessagesEMAIL_SMTP_MAX_MESSAGES | integer, at least 1 |
email.smtp.auth
Left unset, no authentication is sent.
| Setting | Type | Default | Description |
|---|---|---|---|
email.smtp.auth.userEMAIL_SMTP_AUTH_USER | string | Required | |
email.smtp.auth.passEMAIL_SMTP_AUTH_PASS | string | Required |
email.smtp.tls
TLS options passed to Node.js.
| Setting | Type | Default | Description |
|---|---|---|---|
email.smtp.tls.rejectUnauthorizedEMAIL_SMTP_TLS_REJECT_UNAUTHORIZED | boolean | ||
email.smtp.tls.servernameEMAIL_SMTP_TLS_SERVERNAME | string |