Skip to content

Configuration

OpenBot can run as many instances. An instance is one running OpenBot server process. All instances of one deployment use the same database. This page lists the few values that each instance reads when it starts. It also shows where every other setting lives.


The rule

There are two kinds of settings:

  • Instance settings belong to one instance. No other instance needs the same value. They come from environment variables or from files in /run/secrets.
  • Shared settings must be the same on every instance. They live in PostgreSQL. You change them through the API, and every instance uses the change at once.

There is one exception: OPENBOT_SECRET_KEYS. Every instance needs the same keys. But these keys encrypt the secrets in the database, so they cannot live in the database. Each instance reads them from its environment.

If a required value is missing or wrong, OpenBot does not start. It writes a configuration error to the log.


Instance settings

This is the complete list of environment variables that the server reads.

Variable Required Default Meaning
OPENBOT_HOST No 127.0.0.1 The network address that the server listens on.
OPENBOT_PORT No 3000 The port that the server listens on.
OPENBOT_DATABASE_URL Yes A PostgreSQL connection URL.
OPENBOT_SECRET_KEYS Yes The keys that encrypt secrets in the database. See below.
OPENBOT_TLS_CERT No The path to a PEM certificate file.
OPENBOT_TLS_KEY No The path to the PEM private key file for that certificate.

The Docker image sets OPENBOT_HOST=0.0.0.0 and OPENBOT_PORT=3000, so the server can take traffic from outside the container.

Database

OPENBOT_DATABASE_URL looks like this: postgres://openbot:[email protected]:5432/openbot. The server, the migration program, and the setup program all read it.

When the server starts, it checks that all tables exist. If they do not exist, it stops. Run the migration program first. See Deploy.

TLS

Set both OPENBOT_TLS_CERT and OPENBOT_TLS_KEY to make OpenBot serve HTTPS itself. Set neither to serve plain HTTP. If you set only one, OpenBot does not start.

In production, a reverse proxy usually handles HTTPS. Then you leave both values empty. See Deploy.


Secret keys

OpenBot stores some secrets in the database. It encrypts them with the keys in OPENBOT_SECRET_KEYS. These secrets are:

  • the private data of App connections, such as App credentials, private settings, and sign-in state,
  • the API keys of model providers,
  • the client secrets of SSO connections,
  • the sign-in secret of the platform, which signs the sign-in cookies,
  • the client secret of the platform OpenID Connect provider.

OPENBOT_SECRET_KEYS is a list of keys with commas between them:

Terminal window
OPENBOT_SECRET_KEYS=k2:<64 hexadecimal characters>,k1:<64 hexadecimal characters>
  • Each entry is <id>:<key>.
  • The key is exactly 64 hexadecimal characters (32 bytes).
  • The ID is 1 to 32 characters. It can use lowercase letters, digits, _ and -.
  • The first key encrypts new secrets.
  • Every key in the list can decrypt. OpenBot stores the key ID next to each secret, so it knows which key to use.

Make a key once:

Terminal window
echo "k1:$(openssl rand -hex 32)"

Give every instance the same list. Keep the keys together with your database backups. If you lose them, OpenBot cannot read the secrets in the database.

Change the keys

You can add a new key without losing the old secrets:

  1. Make a new key, for example k2.
  2. Put it first in the list, and keep the old key after it: k2:<new>,k1:<old>.
  3. Give the new list to every instance and start them again.

OpenBot now seals new secrets with k2. Secrets that k1 sealed still open. Keep the old key in the list as long as the database holds secrets that it sealed.


Secrets as files

When an environment variable is not set, OpenBot reads the file /run/secrets/<NAME> instead. For example, it reads OPENBOT_SECRET_KEYS from /run/secrets/OPENBOT_SECRET_KEYS. Docker and Compose put secrets in this folder.

  • An environment variable always comes first, even when the file exists.
  • OpenBot removes spaces and line breaks at the start and end of the file.
  • An empty file counts as not set. A missing file or folder also counts as not set.

This works for every variable on this page. It is most useful for secrets, because environment variables show in docker inspect, and files do not.


First setup

A new database has no shared settings. Before people can use OpenBot, you run the setup program once. It writes the first platform settings and the first platform admins.

Until then, the server starts, but every route except /health answers 503 with this body:

{ "_tag": "SetupRequired" }

The log also tells you to run setup. See Platform for all flags and Deploy for the commands.


Where every other setting lives

Every other setting is a shared setting in the database. Two documents hold most of them:

  • The platform settings at /v1/platform/settings. Only platform admins can change them. See Platform.
  • The organization settings at /v1/organization/settings. Each organization has its own. See Organization.

Older versions of OpenBot read more environment variables. OpenBot ignores them now. This table shows where each value went:

Old variable New place
OPENBOT_PUBLIC_ORIGIN publicOrigin in the platform settings. Setup writes it with --public-origin.
OPENBOT_OIDC_ISSUER identityProvider.issuer in the platform settings. Setup writes it with --oidc-issuer.
OPENBOT_OIDC_CLIENT_ID identityProvider.clientId in the platform settings. Setup writes it with --oidc-client-id.
OPENBOT_OIDC_CLIENT_SECRET identityProvider.clientSecret in the platform settings, encrypted. Setup writes it with --oidc-client-secret.
BETTER_AUTH_SECRET The sign-in secret. Setup makes a random one and stores it encrypted. You never set it.
OPENBOT_APP_ENCRYPTION_KEY OPENBOT_SECRET_KEYS.
OPENBOT_OWNER_EMAILS Platform admins. Setup adds them with --admin-email. Change them with /v1/platform/admins.
OPENBOT_ALLOWED_EMAIL_DOMAINS Verified domains of each organization, with joinByDomain in its settings. See SSO.
OPENBOT_MODEL_ENDPOINT Model providers of an organization or of the platform. See Models.
OPENBOT_MODEL_API_KEY Model providers, encrypted.
OPENBOT_MODEL_ID The models of a model provider, and defaultModel in the organization settings.
OPENBOT_DEV_MODE The development entry point decides. See Development.

Some values were options in code before. They are settings now, too:

Old option New place
appRestrictions appRestrictions in the platform settings.
appReadRules appReadRules in the organization settings.
agents.helperModel helperModel in the organization settings.
agents.requestTimeout requestTimeoutMs in the organization settings.
agents.memory agentMemory in the organization settings.
sessions.memory.defaults memory in the organization settings.
allowedEmailDomains, defaultRoles (API) Verified domains, and defaultRoles in the organization settings.

How a change reaches every instance

Each instance keeps the settings in a cache, a short-lived copy in memory. A change works like this:

  1. The API writes the new settings to the database.
  2. It sends a PostgreSQL NOTIFY message on the channel openbot_settings.
  3. Every instance listens on that channel. It reads the new settings at once.

Each cache entry also expires after 30 seconds. So an instance that misses a message still gets the change soon.

A change to publicOrigin, to the platform identity provider, or to the sign-in secret changes how sign-in works. Then each instance starts a new app inside the same process. The new app takes requests first, and then the old one stops. No request is lost.


Production Compose

The Compose file deploy/docker/compose.production.yaml reads these variables. Only the first three reach OpenBot.

Variable Required Default Meaning
POSTGRES_PASSWORD Yes The password of the PostgreSQL user openbot. Use URL-safe characters.
OPENBOT_DATABASE_URL Yes The template fills it in from POSTGRES_PASSWORD.
OPENBOT_SECRET_KEYS Yes The secret keys. See Secret keys.
OPENBOT_RELEASE Yes The image tag to run.
OPENBOT_PUBLISHED_PORT No 8080 The port on 127.0.0.1 where your reverse proxy finds OpenBot.
PROTOCOL_TEST_PUBLIC_ORIGIN Yes The public HTTPS origin of the protocol test service.
PROTOCOL_TEST_ALLOWED_ORIGINS No PROTOCOL_TEST_PUBLIC_ORIGIN Browser origins that the protocol test service accepts.

The Compose file gives OPENBOT_DATABASE_URL and OPENBOT_SECRET_KEYS to OpenBot as files in /run/secrets. The openbot service has no other environment variables. See Deploy. A full template is in deploy/docker/production.env.example.


Development

devenv shell -- pnpm dev:setup makes the file .env.development from .env.development.example. It fills in OPENBOT_SECRET_KEYS with one new random key named dev.

Variable Default Meaning
OPENBOT_SECRET_KEYS dev:<random key>. dev:setup fills it in.
OPENBOT_DEV_HTTPS_PORT 8443 The HTTPS port of the local OpenBot.
OPENBOT_DEV_DATABASE_PORT 5433 The local port of the development PostgreSQL.
OPENBOT_DEV_DATABASE_NAME openbot The name of the development database.

devenv then sets these values for you:

Variable Value
OPENBOT_DEV_PUBLIC_ORIGIN https://localhost:8443
OPENBOT_HOST 127.0.0.1
OPENBOT_PORT the value of OPENBOT_DEV_HTTPS_PORT
OPENBOT_DATABASE_URL postgres://openbot_dev:[email protected]:5433/openbot
OPENBOT_TLS_CERT .devenv/dev/cert.pem, made by mkcert
OPENBOT_TLS_KEY .devenv/dev/key.pem, made by mkcert

Only the development entry point reads OPENBOT_DEV_PUBLIC_ORIGIN. It needs no setup step. At each start, it writes the platform settings for this origin itself. It makes the local account [email protected] a platform admin, and it turns on the local test sign-in. See Authentication.

The production program never uses the local test account. There is no switch for it.

To use another database, set OPENBOT_DATABASE_URL in .env.development. See Contributing.


Example

This is a full production environment file for one instance:

Terminal window
OPENBOT_DATABASE_URL=postgres://openbot:[email protected]:5432/openbot
OPENBOT_SECRET_KEYS=k1:<output of openssl rand -hex 32>

Every other setting comes from the setup program and the API.