Skip to content
Serelane

Configuration

Serelane is configured entirely through the environment, so a container needs no configuration file and nothing mounted to hold one.

Every setting is validated at boot, and every problem is reported at once rather than one restart at a time. A container with no environment at all boots on the defaults below.

Core

VariableDefaultWhat it does
SERELANE_BASE_URLderived from the Host headerThe absolute URL this instance is reachable at. It goes into emails and link previews, which a relative address cannot serve. Must be an absolute http or https URL, and a trailing slash is trimmed. Behind a proxy that does not set Host, the guess is wrong, so set this.
SERELANE_DATA_DIR./dataWhere the database, the uploads and the generated secret key live. The only path Serelane writes to. The container image sets this to /data.
SERELANE_LOG_LEVELinfoOne of debug, info, warn or error.
SERELANE_PORT8080The TCP port to listen on. Between 1 and 65535.
SERELANE_SECRET_KEYgenerated into the data directorySigns sessions, sign-in links and anonymous cookies. At least 32 characters. Left unset, one is generated into secret.key and the instance says so loudly at boot: back that file up, because losing it signs everyone out and invalidates every pending sign-in link.
SERELANE_TRUSTED_PROXIESemptyComma-separated CIDR blocks, or bare addresses for a single host. Only these networks’ X-Forwarded-For is believed. Unset means the header is ignored entirely, so every visitor appears to come from the proxy, which collapses anonymous vote deduplication and rate limiting onto one address.

Database

VariableDefaultWhat it does
SERELANE_DB_DRIVERsqliteThe only accepted value today. Postgres is a planned driver, not a shipped one, and any other value fails at boot.
SERELANE_DB_DSNserelane.db inside the data directoryWhere the database lives. Defaulting inside the data directory is what makes moving that directory move the database with it.

Mail

Mail is optional. With no SERELANE_SMTP_HOST, sign-in links and notifications are written to the log instead of sent, so magic-link identity does not work and nobody is notified of anything.

VariableDefaultWhat it does
SERELANE_SMTP_FROMnoneThe envelope sender. Required once SERELANE_SMTP_HOST is set; the instance refuses to boot without it.
SERELANE_SMTP_HOSTemptyThe relay. Setting it is what turns mail on.
SERELANE_SMTP_PASSWORDemptyThe password for the relay.
SERELANE_SMTP_PORT587The relay’s port.
SERELANE_SMTP_TLSstarttlsOne of starttls (port 587, a plaintext session upgraded), implicit (port 465, TLS from the first byte) or none (in the clear, which is only ever right for a relay on localhost). true, 1 and yes are accepted as synonyms for starttls, and false, 0 and no for none, because this setting used to be a boolean.
SERELANE_SMTP_USERNAMEemptyThe username for the relay.

Spam and abuse

The challenge is instance configuration because the keys are per deployment and because it decides whether the process can verify a solution at all. Which boards actually use it is a per-project setting, in the database.

VariableDefaultWhat it does
SERELANE_CAPTCHA_PROVIDERemptyaltcha, turnstile, or empty for none. Altcha is a self-hosted proof of work and involves no third party, which is why it is the one to reach for first on a self-hosted instance.
SERELANE_CAPTCHA_SECRETthe instance secret keySigns altcha challenges and authenticates to Turnstile. Required for turnstile. In altcha mode it falls back to SERELANE_SECRET_KEY, so the privacy-preserving option needs no configuration beyond switching it on.
SERELANE_CAPTCHA_SITE_KEYemptyThe public half a third-party widget renders with. Required for turnstile.

Sign-in

Both providers reject an explicit email_verified: false assertion. The console requires the ID token to assert email_verified: true, while a board also accepts an omitted optional claim after retrieving the address from subject-matched UserInfo. A provider that omits the claim entirely, which Azure AD and SAML-bridged identity providers do, is refused exactly as if it had sent false — omitting an assertion is not making one. This applies to the admin console provider and the board provider alike.

Admin console

Configures the OIDC provider the operator console signs in through. This is separate from the board provider below: setting one never configures the other, so an instance can require a second factor of its operators without requiring one of every visitor who votes on a roadmap. The client secret is optional here too, since every authorisation request carries a PKCE S256 challenge. Register <base URL>/api/v1/admin/auth/callback as the redirect URI with the provider, using the instance’s own base URL in place of <base URL>. This is a different path from the board provider’s callback below, so a provider can tell the two sign-ins apart.

VariableDefaultWhat it does
SERELANE_ADMIN_OIDC_CLIENT_IDemptyThe application registered with the provider. Required once SERELANE_ADMIN_OIDC_ISSUER is set.
SERELANE_ADMIN_OIDC_CLIENT_SECRETemptyOptional. Every authorisation request carries a PKCE S256 challenge, so a public client is a complete configuration on its own.
SERELANE_ADMIN_OIDC_ISSUERemptyThe provider’s base URL, the one its discovery document hangs off. Required once SERELANE_ADMIN_OIDC_CLIENT_ID is set.
SERELANE_ADMIN_OIDC_LABELemptyWhat the sign-in button says.
SERELANE_ADMIN_OIDC_SCOPESemptySpace-separated. Empty means the default set.

Board provider

Configures one OIDC provider for every board on the instance. It is optional, and when it is set it replaces whatever a project has stored, because a deployment that names its provider here should not have that quietly overridden from a form. Register <base URL>/api/v1/public/auth/callback as the redirect URI with the provider, using the instance’s own base URL in place of <base URL>.

Identities are joined on the verified email address, not on the provider. Pointing an instance at a different provider lets anyone who controls that same address there sign in as the existing identity. They inherit its votes, comments and subscriptions. Only repoint SERELANE_OIDC_ISSUER at a provider you trust to guard the same addresses as the one it replaces.

VariableDefaultWhat it does
SERELANE_OIDC_CLIENT_IDemptyThe application registered with the provider. Required once SERELANE_OIDC_ISSUER is set.
SERELANE_OIDC_CLIENT_SECRETemptyOptional. Serelane always sends a PKCE challenge, so a public client is a complete configuration on its own, and some providers will not issue a secret for one.
SERELANE_OIDC_ISSUERemptyThe provider’s base URL, the one its discovery document hangs off. Required once SERELANE_OIDC_CLIENT_ID is set.
SERELANE_OIDC_LABELemptyWhat the sign-in button says.
SERELANE_OIDC_SCOPESemptySpace-separated. Empty means the default set.

First run

These are read on every invocation but only used by serelane bootstrap, which creates the first admin account without a browser. They live here rather than in flags so that an operator provisioning from a compose file finds them beside every other setting.

VariableDefaultWhat it does
SERELANE_BOOTSTRAP_DEMOon for a dev instance, otherwise offFills the example board with content.
SERELANE_BOOTSTRAP_EMAILnoneThe first admin account’s address. Must contain an @.
SERELANE_BOOTSTRAP_NAMEnoneThe display name on that account.
SERELANE_BOOTSTRAP_PASSWORDnoneThat account’s password. Checked for length up front, so a typo fails the command rather than creating an account nobody can sign in to. Not trimmed: leading and trailing spaces are a legitimate part of a password, and silently changing what you set would lock you out.

Without both an email and a password, serelane bootstrap refuses rather than inventing credentials. Create the account through the setup form instead, at /setup.

Development

VariableDefaultWhat it does
SERELANE_DEVoffSet to 1 to serve the frontend by proxying to the Vite dev server instead of from the embedded copy, and to allow serelane bootstrap to fall back to built-in credentials. Never set this on an instance anyone else can reach.