Skip to content

Configuration

For platform operators. These tasks affect the whole deployment. Have server access or platform admin rights as the task requires. Start with the administrator manual.

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.


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 are two exceptions: OPENBOT_SECRET_KEYS and OPENBOT_CLUSTER_SECRET. Every node needs the same values. They protect stored data and private node messages, so each node reads them from its environment or secret files.

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


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_CLUSTER_SECRET Yes The shared private RPC secret. At least 32 characters.
OPENBOT_CLUSTER_HOST No Bound address The host that other nodes can reach on the server port.
OPENBOT_DATABASE_URL Yes A PostgreSQL connection URL.
OPENBOT_SECRET_KEYS Yes The keys that encrypt secrets in the database. See below.
OPENBOT_OUTBOUND_ALLOW No Private hosts and IP ranges that OpenBot may connect to. See below.

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

Private node calls use /internal/executions/rpc. Keep this path inside your private network. Give every node the same random secret. Set a distinct reachable host for each node when you use more than one node. The private RPC client is separate from the App network guard.

OPENBOT_DATABASE_URL looks like this: postgres://openbot:secret@db.example.com: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.

OpenBot serves plain HTTP only. It has no HTTPS of its own. To serve HTTPS, put a reverse proxy in front of it, such as Caddy or nginx. The proxy holds the certificate and sends the traffic to OpenBot. See Deploy.

OpenBot connects to addresses that people give it, such as model provider endpoints, SSO issuers, custom Channels, and Apps. An attacker could use this to reach your own network. This attack is called server-side request forgery (SSRF).

So OpenBot connects only to public addresses. It blocks these targets:

  • loopback addresses, such as 127.0.0.1, ::1, and localhost,
  • private networks, such as 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and fc00::/7,
  • link-local addresses and cloud metadata services, such as 169.254.169.254,
  • other special ranges, such as shared, test, multicast, and reserved ones.

OpenBot checks the real address of every new connection, after the DNS lookup. It also checks each redirect. A host name that points to a private address is blocked, too.

To open a private target on purpose, list it in OPENBOT_OUTBOUND_ALLOW. Separate the entries with commas. Each entry is one of these:

Entry Example What it opens
An IP address 127.0.0.1, ::1 This one address.
An IP range 10.20.0.0/16, fd00::/8 Every address in the range, for any host name.
A host name localhost, ollama.internal This exact name, whatever address it points to. No other name.

There are no wildcards and no ports. If an entry is wrong, OpenBot does not start.

Terminal window
# A model server on the same machine, and one internal network.
OPENBOT_OUTBOUND_ALLOW=localhost,10.20.0.0/16

When OpenBot blocks a connection, the error and the log name the host and OPENBOT_OUTBOUND_ALLOW.


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.

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.


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.


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.


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 A model that a model provider links, and the model of each Bot.
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.
bots.helperModel rulesModel and botMemoryModel in the organization settings.
bots.requestTimeout requestTimeoutMs in the organization settings.
bots.memory botMemory in the organization settings.
sessions.memory.defaults Nothing. The learned memory of each Session is gone.
allowedEmailDomains, defaultRoles (API) Verified domains, and defaultRoles in the organization settings.

Each settings read uses the committed database row. A change works like this:

  1. The API writes the new settings in a transaction.
  2. PostgreSQL sends NOTIFY on openbot_settings when that transaction commits.
  3. Subscribers use the notice to react to the change. The next read sees the row even if a notice is lost.

There is no settings cache that can keep old access rights. A failed read fails the action. App restrictions do not become empty when their store is down. A list reads one restriction snapshot, so all its entries use the same rules.

If the listener connection breaks, it logs the failure and listens again after one second. Reads still use the database while the listener reconnects.

A change to publicOrigin, to the platform identity provider, or to the sign-in secret changes how sign-in works. Each instance reads these values when it uses them, so the next request uses the new values. Sign-in gets a new setup for them, and the old setup closes a few minutes after its last request. Nothing starts again: requests and Turns that are running go on.


The Compose file deploy/docker/compose.production.yaml reads these variables. Only OPENBOT_DATABASE_URL, OPENBOT_SECRET_KEYS, and OPENBOT_OUTBOUND_ALLOW 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_OUTBOUND_ALLOW No Private targets to open. See Outbound connections.
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. It gives OPENBOT_OUTBOUND_ALLOW as an environment variable. The openbot service has no other environment variables. See Deploy. A full template is in deploy/docker/production.env.example.


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_DATABASE_NAME openbot The name of the development database.

devenv then sets these values for you. devenv picks each port: it starts at the base port and takes the next free one. It gives the values with a port only to the OpenBot process, not to devenv shell.

Variable Value
OPENBOT_DEV_PUBLIC_ORIGIN http://localhost
OPENBOT_HOST 127.0.0.1
OPENBOT_PORT a free port, from 3000
OPENBOT_DATABASE_URL postgres://openbot_dev:openbot_dev@127.0.0.1:<port>/openbot, with a free port from 5433
OPENBOT_DEV_S3_ENDPOINT http://127.0.0.1:<port>, with a free port from 9000
OPENBOT_DEV_S3_BUCKET openbot

The devenv proxy serves OpenBot at http://localhost, on port 80. Development needs no HTTPS. Browsers and curl keep the secure sign-in cookie on localhost, also without HTTPS.

The proxy listens on port 80. If another program uses it, give the proxy another port in your shell, such as DEVENV_PROXY_LISTEN=127.0.0.1:8080. Then set OPENBOT_DEV_PUBLIC_ORIGIN=http://localhost:8080 in .env.development. With a port above 1023, the proxy needs no sudo.

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 developer@localhost.test 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.

The development server blocks private targets, too. To use a model server on your machine, such as Ollama, set OPENBOT_OUTBOUND_ALLOW=localhost in .env.development. See Outbound connections.

devenv also starts RustFS, a small object storage, for files. It runs in Docker. Its data lives in the Docker volume openbot-dev-rustfs. At each start, the development entry point makes the bucket openbot and writes the storage into the platform settings. RustFS is at 127.0.0.1, a private address. So the development entry point opens that one host for itself. You do not need to add it to OPENBOT_OUTBOUND_ALLOW.

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


This is a full production environment file for one instance:

Terminal window
OPENBOT_DATABASE_URL=postgres://openbot:secret@db.example.com:5432/openbot
OPENBOT_SECRET_KEYS=k1:<output of openssl rand -hex 32>

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