DOCS

Configuration.

Every setting the server reads, what it does, and what happens if you leave it alone. Most deployments touch fewer than ten.

How settings are spelled

Configuration comes from appsettings.json under a Bakn section, or from environment variables — which is what a container deployment uses. The two spellings map onto each other: nesting becomes a double underscore.

Bakn:Oidc:ClientId        (json)
Bakn__Oidc__ClientId      (environment)

Arrays are indexed: Bakn__CorsOrigins__0, Bakn__CorsOrigins__1. Environment variables win over the file.

Never put a secret in appsettings.json. That file ships inside the public container image, so anything written there is shared by every operator of that image and readable by anyone who pulls it. Secrets belong in the environment.

Core

SettingDefaultWhat it does
Database Connection string. A postgresql:// URL or Npgsql keywords for Postgres; Data Source=/data/bakn.db for SQLite. Empty means in-memory, which loses everything on restart.
DatabaseProviderauto postgres, sqlite, or auto to infer from the connection string's shape. Say it explicitly in production: a malformed string then fails loudly instead of quietly starting on the other provider.
FileStorePathbakn-files Directory for attachments. Ignored when Spaces is configured. Must be on a volume that survives redeploys.
SeedDemoDatafalse Creates a demo channel at startup. Development only.

Accounts and access

SettingDefaultWhat it does
AllowSelfRegistrationunset Operator override for POST /auth/register. Unset defers to the admin-editable setting in the app, which starts open. Set false to close it before the server ever accepts a request; an admin then cannot re-open it. Does not affect SSO.
DefaultAdmin:UserNameAdmin Name of the bootstrap admin account.
DefaultAdmin:Password Applied on the first start only, while that account has no password. Changing it later does nothing. No default ships, deliberately.
AdminUserNamesempty Usernames granted admin authority, resolved to user ids at startup.
MinPasswordLength10 Minimum length for password registration and changes.
TokenLifetimeDays7 Session token lifetime.
AccessTokenLifetimeHoursunset Shortens the access token independently of the session, if you want refreshes to happen more often.
RefreshTokenLifetimeDays30 How long a client can stay away and still refresh rather than sign in again.
MaxSocketsPerUser5 Concurrent realtime connections per account — roughly, devices.

Single sign-on

Full walkthrough on the SSO page.

SettingDefaultWhat it does
Oidc:AuthorityIssuer URL. Discovery is resolved from it.
Oidc:ClientIdClient id at the provider. SSO enables once this and Authority are both set.
Oidc:ClientSecretFor confidential clients. Omit for public ones; PKCE is always used.
Oidc:Scopesopenid profile emailScopes requested.
Oidc:ProviderDisplayNameSSOLabel on the client's sign-in button.
Oidc:PublicBaseUrlrequest hostThis server's external URL, used to build the redirect URI. Set it behind a proxy — otherwise the server derives an internal address the provider will reject.
Oidc:AdminRoleClaimClaim consulted for admin membership, e.g. roles.
Oidc:AdminRoleValueValue in that claim which grants admin. With both set, the provider is authoritative on every sign-in.
Oidc:AllowedRedirectSchemesbaknURI schemes the post-login redirect into the app may use. Loopback is always allowed, for the desktop client.

Network and TLS

SettingDefaultWhat it does
TrustedProxiesempty Required behind a reverse proxy. Without it every request appears to come from the proxy, so per-IP rate limiting collapses into one shared bucket and failed-login lockout keys on the proxy — meaning anyone can lock out any account. 172.16.0.0/12 covers Docker's bridge ranges.
RequireHttpsauto Set false when a proxy terminates TLS and forwards plain HTTP; the proxy should issue the redirect instead.
CorsOriginsempty Browser origins allowed to call the API. Not needed for the desktop and mobile clients.

Calling

SettingDefaultWhat it does
Turn:UrisTURN URIs handed to clients. Must be publicly resolvable — an internal Docker name yields zero usable candidates rather than an error.
Turn:StaticAuthSecretShared secret with coturn. The server derives per-user, time-limited credentials from it, so coturn needs no user database.
Turn:CredentialTtlMinutes60Lifetime of an issued TURN credential.
IceServersemptyAdditional static ICE servers, if you are not using the derived-credential path.

Files, retention and scanning

SettingDefaultWhat it does
PerUserDailyUploadQuotaBytes250 MBPer-account upload allowance per day.
AllowedUploadContentTypesunsetAllow-list of MIME types. Unset permits anything the type sniffer accepts.
RetentionunsetTTLs for messages, sessions and orphaned files. Unset keeps everything forever.
ClamAvunsetAddress of a ClamAV daemon to scan uploads through.
Spaces:*unsetS3-compatible attachment storage — ServiceUrl, Bucket, AccessKey, SecretKey, Region, Prefix. Configuring it replaces the local file store. ServiceUrl is the regional endpoint and must not include the bucket.

Observability and clients

SettingDefaultWhat it does
JsonConsoleLogsfalseStructured JSON logs, for a log collector.
MetricsEnabledfalseExposes a Prometheus endpoint.
MetricsTokenBearer token required to scrape it. Set one if the endpoint is reachable off-box.
OtlpEndpointOTLP collector for traces.
SignaturePolicyAcceptUnsignedHow strictly message signatures are enforced.
LatestClientVersionAdvertised by /api/v1/version so clients can offer an update.
MinimumClientVersionOldest supported client. Advisory: the version arrives in a caller-supplied header, so it explains a failure rather than preventing one.

Checking what took effect

Two anonymous endpoints report the settings that are visible from outside:

curl https://chat.example.com/api/v1/version
curl https://chat.example.com/api/v1/auth/config

/auth/config answers whether registration is open and whether SSO is enabled — which is the fastest way to tell a server that is not configured from a client that is not asking.

Burn the dead zones.

Free on every platform. Your first message sends in under a minute — and keeps sending when nothing else does.

An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.