Configuration
Odudu is configured by environment variables, read once when the server or a command starts. A value that does not fit its type or bounds stops it from starting, and the message names the variable. A variable marked secret holds a credential: keep it out of images, logs and source control.
What you must set
The server does not start without ODUDU_DATABASE_URL and ODUDU_KEK. The console is on by default, so by default it also needs the variables below; set ODUDU_CONSOLE=false to run without it.
ODUDU_APP_DATABASE_URL, whenNODE_ENVisproduction.ODUDU_TLS, whenNODE_ENVisproduction, where it must betrue.ODUDU_SMTP_FROM, whenODUDU_SMTP_HOSTis set.ODUDU_PUBLIC_BASE_URL, when the console is on (ODUDU_CONSOLE, which defaults totrue) orNODE_ENVisproduction.ODUDU_CONSOLE_CLIENT_KEY, when the console is on (ODUDU_CONSOLE, which defaults totrue).
Server
| Variable | Type | Default | Description |
|---|---|---|---|
NODE_ENV | one of development, test, production | development | The environment the server runs in. production makes the server refuse to boot unless it has ODUDU_APP_DATABASE_URL, ODUDU_TLS=true, ODUDU_PUBLIC_BASE_URL and a ODUDU_KEK that is not the published example, and with ODUDU_ALLOW_PRIVATE_CLIENT_URLS off. |
ODUDU_HTTP_HOST | string | 0.0.0.0 | The address the HTTP server listens on. |
ODUDU_HTTP_PORT | integer, 1 to 65,535 | 3000 | The port the HTTP server listens on. |
ODUDU_TRUST_PROXY | true or false | false | Whether to trust what a reverse proxy in front of the server reports about the client: its address, which is recorded in audit events and keys the rate limits. It does not decide the issuer or any cookie. Turn it on only behind a proxy that overwrites X-Forwarded-*. |
ODUDU_TLS_CLIENT_CERT_HEADER | string | x-ssl-client-s-dn | The header a proxy puts the subject of a client certificate in, read for tls_client_auth at the token endpoint and only while ODUDU_TRUST_PROXY is on. Compared in lower case. |
ODUDU_TLS | true or false | none; required when NODE_ENV is production, where it must be true | States that the connection to the user is HTTPS, terminated here or by a proxy in front of the server. It gives every cookie Secure and a __Host- or __Secure- name, and NODE_ENV=production refuses to boot while it is off. |
ODUDU_LOG_LEVEL | one of fatal, error, warn, info, debug, trace, silent | info | The lowest severity the server logs. silent logs nothing. |
ODUDU_PUBLIC_BASE_URL | string | none; required when the console is on (ODUDU_CONSOLE, which defaults to true) or NODE_ENV is production | The origin the server is reached at, with no path: the issuer of every tenant, the base every mailed link and the console’s redirect URI are built from, and the source of the passkey relying party id. Never taken from a request header. Required when NODE_ENV=production. Without it (local development) the issuer is read from the request. |
ODUDU_INSTRUMENT_DIR | string | /app/instrument | The directory of the stylesheet and fonts every server-rendered page links. |
ODUDU_DOCS | true or false | true | Whether the server serves its documentation under /docs, on its own address. Set false to turn the route off; /docs then answers 404. |
ODUDU_DOCS_DIR | string | /app/docs | The directory of the built documentation, as the release image lays it out. A directory with no build, or one that is not the build, makes the documentation answer 503 and the log names this variable; the rest of the server starts. |
Database
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_DATABASE_URL | URL, secret | required | The PostgreSQL connection URL of the owner role. The server applies migrations with it at start and odudu init creates the service role with it. It can switch row-level security off, so production serves traffic through ODUDU_APP_DATABASE_URL instead. |
ODUDU_MIGRATIONS_DIR | string | none | A directory of migrations to apply in place of the ones built into the release. |
ODUDU_APP_DATABASE_URL | URL, secret | none; required when NODE_ENV is production | The PostgreSQL connection URL of the role the server serves traffic with, which row-level security applies to. Required when NODE_ENV=production. Commands that read every tenant refuse a role that is a superuser or bypasses row-level security. |
Encryption
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_KEK | string, secret | required | The key-encryption key: 32 random bytes, base64-encoded. It wraps every signing key and console session token and keys pagination cursors, so changing it makes the stored keys unreadable. Generate one with openssl rand -base64 32. |
Rate limits
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_THROTTLE_LIMIT | integer, 1 to 10,000 | 10 | Requests allowed per origin in each window on the routes that cost a password hash or a mail send. Over the budget the server answers 429. |
ODUDU_THROTTLE_WINDOW_SECONDS | integer, 1 to 3,600 | 60 | The length of the per-origin window, in seconds. |
ODUDU_LOGIN_THROTTLE_LIMIT | integer, 1 to 10,000 | 5 | Sign-in submissions allowed per address and username in each window. |
ODUDU_LOGIN_THROTTLE_WINDOW_SECONDS | integer, 1 to 3,600 | 60 | The length of the sign-in window, in seconds. |
ODUDU_CLIENT_SECRET_THROTTLE_LIMIT | integer, 1 to 10,000 | 5 | Failed client_secret_basic and client_secret_post attempts allowed per client in each window at the token endpoint. |
ODUDU_CLIENT_SECRET_THROTTLE_WINDOW_SECONDS | integer, 1 to 3,600 | 60 | The length of the client secret window, in seconds. |
Retention
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_RETENTION_GRANT_SECONDS | integer, 60 to 31,536,000 | 604800 | How long odudu reap keeps a grant (refresh token family) after nothing can read it. A retention window, not a lifespan: it can raise how long rows are kept, never lower it below what reuse detection needs. |
ODUDU_RETENTION_OFFLINE_GRANT_SECONDS | integer, 60 to 31,536,000 | 2592000 | The retention window of an offline grant, the same kind of window as ODUDU_RETENTION_GRANT_SECONDS. |
ODUDU_RETENTION_AUTHORIZATION_CODE_SECONDS | integer, 60 to 31,536,000 | 3600 | How long an authorization code that never produced a grant is kept. A code that did is removed with the grant family it produced. |
ODUDU_RETENTION_AUTHENTICATION_SESSION_SECONDS | integer, 60 to 31,536,000 | 3600 | How long a finished or expired sign-in attempt is kept. This is where most of the rows are. |
ODUDU_RETENTION_ACTION_TOKEN_SECONDS | integer, 60 to 31,536,000 | 604800 | How long a spent or expired mailed action token, or a registration nobody opened, is kept. |
ODUDU_RETENTION_REGISTRATION_TOKEN_SECONDS | integer, 60 to 31,536,000 | 604800 | How long a spent or expired registration token is kept. |
ODUDU_RETENTION_SESSION_SECONDS | integer, 60 to 31,536,000 | 86400 | How long an ended or expired user session is kept. |
ODUDU_RETENTION_EMAIL_SENT_SECONDS | integer, 60 to 31,536,000 | 604800 | How long a delivered email stays in the outbox, counted from its delivery, so an operator can answer whether a link ever went out. |
ODUDU_RETENTION_EMAIL_FAILED_SECONDS | integer, 3,600 to 31,536,000 | 2592000 | How long an email that used up every attempt stays, counted from its last attempt. Long, because nothing else records the failure. |
ODUDU_RETENTION_LOGOUT_DELIVERED_SECONDS | integer, 60 to 31,536,000 | 604800 | How long a delivered back-channel logout is kept, counted from its delivery. |
ODUDU_RETENTION_LOGOUT_FAILED_SECONDS | integer, 3,600 to 31,536,000 | 2592000 | How long a back-channel logout that used up every attempt is kept, counted from its last attempt. |
Background passes
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_REAP_ENABLED | true or false | true | Whether the server runs the retention pass itself. Set it to false when you schedule odudu reap externally, for example as a cron entry or a Kubernetes CronJob. |
ODUDU_REAP_INTERVAL_SECONDS | integer, 60 to 86,400 | 3600 | Seconds between retention passes, plus up to a tenth of that as random jitter. |
ODUDU_OUTBOX_ENABLED | true or false | true | Whether the server sends queued email itself. Set it to false when you schedule odudu send-mail; with neither running, queued mail is never sent. |
ODUDU_OUTBOX_INTERVAL_SECONDS | integer, 5 to 86,400 | 15 | Seconds between passes that send queued email. |
ODUDU_OUTBOX_BATCH_SIZE | integer, 1 to 1,000 | 20 | Messages sent per tenant in one pass, so one tenant’s backlog cannot starve another’s. |
ODUDU_OUTBOX_MAX_ATTEMPTS | integer, 1 to 100 | 5 | Attempts a message gets before it is left for an operator to read. Lowering it reclassifies messages already queued: one past the new ceiling stops being retried and starts its failed-email retention window. |
ODUDU_OUTBOX_RETRY_BACKOFF_SECONDS | integer, 1 to 86,400 | 60 | The delay before the first retry of a message; each further attempt doubles it. |
ODUDU_LOGOUT_SENDER_ENABLED | true or false | true | Whether the server delivers back-channel logout tokens itself. Set it to false when you schedule odudu send-logouts; with neither running, relying parties of an ended session are never told. |
ODUDU_LOGOUT_SENDER_INTERVAL_SECONDS | integer, 5 to 86,400 | 15 | Seconds between passes that deliver back-channel logout tokens. |
ODUDU_LOGOUT_SENDER_BATCH_SIZE | integer, 1 to 1,000 | 20 | Deliveries claimed per tenant in one pass. |
ODUDU_LOGOUT_SENDER_LEASE_SECONDS | integer, 1 to 3,600 | 30 | How long a claimed delivery stays invisible to other passes: what a process killed between claiming and sending costs. |
ODUDU_LOGOUT_SENDER_RESPONSE_TIMEOUT_MS | integer, 100 to 60,000 | 5000 | Milliseconds one delivery may take, connecting and answering together, before it is abandoned for this pass. |
Mail
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_SMTP_HOST | string | none | The SMTP relay to send mail through. Unset, the server logs each message instead of sending it. Needs ODUDU_SMTP_FROM. |
ODUDU_SMTP_PORT | integer, 1 to 65,535 | 587 | The port of the SMTP relay. |
ODUDU_SMTP_FROM | string | none; required when ODUDU_SMTP_HOST is set | The address mail is sent from. Required when ODUDU_SMTP_HOST is set. |
ODUDU_SMTP_USERNAME | string | none | The user name to authenticate to the SMTP relay with. |
ODUDU_SMTP_PASSWORD | string, secret | none | The password to authenticate to the SMTP relay with. |
ODUDU_SMTP_STARTTLS | true or false | false | Whether to require STARTTLS before sending. It is required whenever ODUDU_SMTP_USERNAME and ODUDU_SMTP_PASSWORD are set, so credentials never travel in the clear. |
Admin console
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_CONSOLE | true or false | true | Whether the server serves the admin console under /console. While on it needs ODUDU_PUBLIC_BASE_URL and ODUDU_CONSOLE_CLIENT_KEY. |
ODUDU_CONSOLE_CLIENT_KEY | string, secret | none; required when the console is on (ODUDU_CONSOLE, which defaults to true) | The private key the console authenticates with as every tenant’s built-in admin client: an ES256 JWK, base64-encoded. odudu console keygen prints a new one. Required while the console is on. |
ODUDU_CONSOLE_CLIENT_KEY_PREVIOUS | string, secret | none | The key being replaced, kept registered on every tenant until the pass that drops it. A private or a public JWK, base64-encoded; only the public half is used. |
ODUDU_CONSOLE_DIR | string | /app/console | The directory of the built console’s static files, as the release image lays it out. |
Outbound requests
| Variable | Type | Default | Description |
|---|---|---|---|
ODUDU_ALLOW_PRIVATE_CLIENT_URLS | true or false | false | Lets the server fetch a client’s jwks_uri or send its back-channel logout to a private address. For development and conformance testing; NODE_ENV=production refuses to boot with it on. A loopback address is refused regardless. |
ODUDU_ALLOW_PRIVATE_SMTP_HOSTS | true or false | false | Lets a tenant’s own SMTP relay (set through the admin API) be at a private address, which an internal relay legitimately is. Not refused under NODE_ENV=production. Loopback, link-local and multicast addresses are refused regardless. |
Read by commands and the image
These are read from the environment by a command or the release image rather than by the server’s configuration, so a mistake in them does not stop the server.
| Variable | Description |
|---|---|
ODUDU_ADMIN_EMAIL | The address odudu init gives the first administrator when --admin-email is not passed. A blank value counts as unset. |
ODUDU_ADMIN_PASSWORD | The password odudu init gives the first administrator in place of a generated one. It is an environment variable and never an option, so it does not appear in a process listing. A blank value counts as unset. |
ODUDU_VERSION | The version odudu --version prints. The release image sets it; elsewhere it is dev. |