Configuration
You configure Umpteenth in a YAML file, config.yml, and override single options with environment variables.
The config file
Section titled “The config file”docker-compose.yml mounts config.yml from its own directory into the container at /app/config.yml, where Umpteenth looks for it:
services: umpteenth: volumes: - ./config.yml:/app/config.yml:roStart from config.example.yml in the repository, which lists every option with its default and a comment.
Options you leave out or leave empty keep their defaults, so a short file is enough:
app: url: https://umpteenth.example.com encryption_key: "<output of openssl rand -base64 32>"
auth: providers: pocket-id: type: oidc name: Pocket ID issuer: https://id.example.com client_id: umpteenth client_secret: "<client secret>"Umpteenth reads the file once, when it starts, so restart it after an edit:
docker compose restart umpteenthWithout a config.yml, Umpteenth falls back to config.yaml.
To keep the file somewhere else in the container, point CONFIG_FILE or the --config flag at it, and Umpteenth refuses to start if that file is missing.
Environment variables
Section titled “Environment variables”Each option has an environment variable named after its path, in upper case with underscores for dots and hyphens, so server.trust_proxy is SERVER_TRUST_PROXY and auth.providers.pocket-id.allowed_groups is AUTH_PROVIDERS_POCKET_ID_ALLOWED_GROUPS.
Umpteenth applies its defaults first, then config.yml, then the environment, so a variable wins over the file.
Set variables in the environment: block of the service:
services: umpteenth: environment: LOG_LEVEL: debug AUTH_PROVIDERS_POCKET_ID_ALLOWED_GROUPS: admins,opsApply a change to environment: with docker compose up -d, which recreates the container.
docker compose restart keeps the old environment.
An empty variable counts as unset and keeps the value from the file.
Lists take commas, as in admins,ops, and durations take a unit, such as 90m or 12h.
Docker Compose reads a .env file next to docker-compose.yml to fill ${...} placeholders in the compose file, and passes nothing from it to Umpteenth on its own.
To use a variable from .env, reference it in environment:, such as LOG_LEVEL: ${LOG_LEVEL}, or add env_file: .env to the service.
Values from files
Section titled “Values from files”Append _FILE to any variable to read its value from a file, the way Docker secrets work:
services: umpteenth: environment: APP_ENCRYPTION_KEY_FILE: /run/secrets/encryption_key secrets: - encryption_key
secrets: encryption_key: file: ./encryption_key.txtUmpteenth trims whitespace around the content, so a trailing newline does no harm.
Set a variable or its _FILE variant, not both, or Umpteenth refuses to start with set either APP_ENCRYPTION_KEY or APP_ENCRYPTION_KEY_FILE, not both.
Errors at start
Section titled “Errors at start”Umpteenth checks the configuration before it opens the database, and a typo in the file or an invalid value stops it with an error that names the option.
Read the error with docker compose logs umpteenth:
Error: config.yml: line 4: unknown option server.protError: unknown file_storage.backend (FILE_STORAGE_BACKEND) "nfs", use filesystem, s3 or databaseWorkspace defaults
Section titled “Workspace defaults”Three options set defaults for fields you can also change under Settings → General:
| Option | Field |
|---|---|
sandbox.image |
Default image on the Sandbox defaults card |
runs.daily_spend_limit_usd |
Daily spend limit on the Spend and retention card |
runs.retention_days |
Retention on the Spend and retention card |
Each workspace uses the option’s current value until someone saves the card that holds the field in that workspace.
Saving a card stores every field on it, so a change to Memory on the Sandbox defaults card stores Default image too.
From then on, edits to sandbox.image leave that workspace’s default image alone.
Options
Section titled “Options”Each row shows the option’s path in config.yml above its environment variable.
| Option | Default | Description |
|---|---|---|
app.urlAPP_URL |
http://localhost:8080 |
The URL you open Umpteenth at. Each sign-in provider’s redirect URI is <app.url>/api/auth/callback/<id>, and links in notifications point to runs under it. With an https:// URL, Umpteenth marks its cookies Secure, see Reverse proxy. |
app.encryption_keyAPP_ENCRYPTION_KEY |
none, required | At least 16 bytes, such as the output of openssl rand -base64 32. Encrypts secrets, provider API keys and MCP logins, and signs sessions. Under a different key, Umpteenth can’t decrypt what it stored and everyone has to sign in again, so keep a copy with your backups. |
app.data_dirAPP_DATA_DIR |
data, which is /app/data in the container |
Holds the SQLite database and stored files, unless database.connection_string or file_storage.path point elsewhere. |
Sign-in
Section titled “Sign-in”Each sign-in provider has these options below its ID, and Sign-in shows how to set up both types.
The options from issuer on apply to one type only, and setting one on a provider of the other type stops Umpteenth at start.
| Option | Default | Description |
|---|---|---|
auth.providers.<id>.typeAUTH_PROVIDERS_<ID>_TYPE |
none, required | oidc for an OpenID Connect identity provider, or github for GitHub accounts. |
auth.providers.<id>.nameAUTH_PROVIDERS_<ID>_NAME |
none, required | The label of the provider’s button, which reads Sign in with and the name. |
auth.providers.<id>.iconAUTH_PROVIDERS_<ID>_ICON |
empty | An image for the button, as an http:// or https:// URL or a data:image/ URI. Without one, or if it fails to load, a github provider shows the GitHub mark and an oidc provider a generic sign-in icon. |
auth.providers.<id>.primaryAUTH_PROVIDERS_<ID>_PRIMARY |
false |
Gives the provider the large button at the top of the login page. At most one provider can be primary. |
auth.providers.<id>.client_idAUTH_PROVIDERS_<ID>_CLIENT_ID |
none, required | The client ID of the OpenID Connect client or the GitHub OAuth app. |
auth.providers.<id>.client_secretAUTH_PROVIDERS_<ID>_CLIENT_SECRET |
empty, required for github |
The client secret. Umpteenth signs in with PKCE, so a public OpenID Connect client without a secret works too. |
auth.providers.<id>.issuerAUTH_PROVIDERS_<ID>_ISSUER |
none, required for oidc |
oidc only. The issuer URL of the identity provider, starting with http:// or https://. Umpteenth fetches its discovery document from inside the container at the first sign-in through this provider, so the URL has to work there, where localhost is the container itself. |
auth.providers.<id>.allowed_groupsAUTH_PROVIDERS_<ID>_ALLOWED_GROUPS |
empty | oidc only. Groups whose members may sign in through this provider. Umpteenth compares them, case included, with the ID token’s groups claim. Empty admits everyone the identity provider lets through. |
auth.providers.<id>.admin_groupsAUTH_PROVIDERS_<ID>_ADMIN_GROUPS |
empty | oidc only. Groups whose members are instance admins and may sign in even when allowed_groups leaves them out. Umpteenth checks them at every sign-in. |
auth.providers.<id>.allowed_usersAUTH_PROVIDERS_<ID>_ALLOWED_USERS |
empty | github only. GitHub usernames that may sign in, compared ignoring case. |
auth.providers.<id>.allowed_organizationsAUTH_PROVIDERS_<ID>_ALLOWED_ORGANIZATIONS |
empty | github only. GitHub organizations whose active members may sign in. A github provider needs this list, allowed_users, or one of the admin lists. |
auth.providers.<id>.admin_usersAUTH_PROVIDERS_<ID>_ADMIN_USERS |
empty | github only. GitHub usernames of instance admins, who may sign in even when the allow lists leave them out. |
auth.providers.<id>.admin_organizationsAUTH_PROVIDERS_<ID>_ADMIN_ORGANIZATIONS |
empty | github only. GitHub organizations whose active members are instance admins. |
Workspaces
Section titled “Workspaces”| Option | Default | Description |
|---|---|---|
workspaces.enabledWORKSPACES_ENABLED |
false |
Lets people create workspaces, invite others and switch between them. Off, everyone who signs in shares one workspace, see Workspaces. |
Server
Section titled “Server”| Option | Default | Description |
|---|---|---|
server.hostSERVER_HOST |
0.0.0.0 |
The interface both listeners bind to. Sandboxes reach the broker over Docker networks, so keep the default in a container. |
server.portSERVER_PORT |
8080 |
The UI, the API and job webhooks. |
server.broker_portSERVER_BROKER_PORT |
8081 |
The broker, the API that the ump CLI inside sandboxes calls for models, MCP tools and job state. Keep it unpublished. |
server.trust_proxySERVER_TRUST_PROXY |
false |
Takes the client address for the login rate limit from X-Forwarded-For. Turn it on only behind a reverse proxy. |
| Option | Default | Description |
|---|---|---|
log.levelLOG_LEVEL |
info |
debug, info, warn or error, and any other value stops the server. At debug Umpteenth logs every API request, at info the failed ones. |
log.jsonLOG_JSON |
false |
JSON lines instead of text. |
Database
Section titled “Database”| Option | Default | Description |
|---|---|---|
database.connection_stringDATABASE_CONNECTION_STRING |
<app.data_dir>/umpteenth.db |
A SQLite file path, or a Postgres URL starting with postgres:// or postgresql://, such as postgres://umpteenth:secret@db:5432/umpteenth?sslmode=disable. Umpteenth treats anything else as a SQLite path, a host=db user=umpteenth connection string included. |
File storage
Section titled “File storage”| Option | Default | Description |
|---|---|---|
file_storage.backendFILE_STORAGE_BACKEND |
filesystem |
The store for artifacts, long tool outputs and image build logs: filesystem, s3, or database for a table in the database. |
file_storage.pathFILE_STORAGE_PATH |
<app.data_dir>/blobs |
The directory of the filesystem backend. |
file_storage.s3.endpointFILE_STORAGE_S3_ENDPOINT |
empty, meaning AWS S3 | A host with a port, such as s3.example.com:9000, or a URL, such as http://s3:8333. |
file_storage.s3.bucketFILE_STORAGE_S3_BUCKET |
empty | The bucket, which Umpteenth creates at start if it’s missing. |
file_storage.s3.regionFILE_STORAGE_S3_REGION |
empty | The region of the bucket. |
file_storage.s3.access_key_idFILE_STORAGE_S3_ACCESS_KEY_ID |
empty | The access key. |
file_storage.s3.secret_access_keyFILE_STORAGE_S3_SECRET_ACCESS_KEY |
empty | The secret key. |
file_storage.s3.use_sslFILE_STORAGE_S3_USE_SSL |
true |
TLS for an endpoint given as a host. An endpoint given as a URL takes TLS from its scheme. |
Sandboxes
Section titled “Sandboxes”| Option | Default | Description |
|---|---|---|
sandbox.imageSANDBOX_IMAGE |
ghcr.io/stonith404/umpteenth-sandbox:latest |
The workspace default of Default image. Umpteenth pulls it at start if the engine lacks it, and runs its own helper containers from it. |
sandbox.egress_filterSANDBOX_EGRESS_FILTER |
auto |
auto, required or off, for the firewall rules that keep internet sandboxes off private networks, see Security. |
sandbox.docker.runtimeSANDBOX_DOCKER_RUNTIME |
runc |
The runtime of sandbox containers, runsc for gVisor. |
sandbox.docker.dnsSANDBOX_DOCKER_DNS |
empty, 8.8.8.8 and 8.8.4.4 under gVisor |
The resolvers of Internet access sandboxes under gVisor. Set it only together with runsc. |
sandbox.registry.repositorySANDBOX_REGISTRY_REPOSITORY |
empty | A registry path without a scheme, such as ghcr.io/acme/umpteenth-jobs. Umpteenth pushes the image of each job with its own Dockerfile below it, as <path>/job-<job id>, so other replicas pull it instead of building it again. Umpteenth never deletes tags there, so give the registry a cleanup policy. |
sandbox.registry.usernameSANDBOX_REGISTRY_USERNAME |
empty | The user for pushes and pulls. |
sandbox.registry.passwordSANDBOX_REGISTRY_PASSWORD |
empty | The password or token of that user. |
Umpteenth finds Docker or Podman through the standard Docker client variables DOCKER_HOST, DOCKER_TLS_VERIFY and DOCKER_CERT_PATH, which have no key in config.yml.
Without them it uses the socket at /var/run/docker.sock.
If Umpteenth can’t reach the engine, it refuses to start and logs failed to reach the container engine.
| Option | Default | Description |
|---|---|---|
runs.max_concurrentRUNS_MAX_CONCURRENT |
3 |
Runs executing at once on this replica. More runs wait as queued. |
runs.daily_spend_limit_usdRUNS_DAILY_SPEND_LIMIT_USD |
0, meaning no limit |
The workspace default of Daily spend limit, see Models and costs. |
runs.retention_daysRUNS_RETENTION_DAYS |
90 |
The workspace default of Retention. Every night Umpteenth deletes the events and files of runs that finished longer ago than that, and keeps the run records. |
Network
Section titled “Network”| Option | Default | Description |
|---|---|---|
network.allow_private_targetsNETWORK_ALLOW_PRIVATE_TARGETS |
true |
Lets Umpteenth itself call model providers, HTTP MCP servers and notification webhooks at private or local addresses. Sandboxes follow their job’s network setting instead, see Security. |
Models
Section titled “Models”| Option | Default | Description |
|---|---|---|
models.catalog_refresh_intervalMODELS_CATALOG_REFRESH_INTERVAL |
12h |
The interval at which Umpteenth downloads the models.dev catalog and syncs every provider’s model list, see Models and costs. 0 turns the refresh off, so Umpteenth uses the newer of the catalog it downloaded last and the one built into it. Any other value must be at least 5m. |
providers.anthropic_api_keyPROVIDERS_ANTHROPIC_API_KEY |
empty | The API key of the Anthropic provider Umpteenth creates on its first start, in the Default workspace. Later starts ignore it, so change keys under Settings → Providers & models, and workspaces people create get the provider without a key. |
High availability
Section titled “High availability”| Option | Default | Description |
|---|---|---|
ha.enabledHA_ENABLED |
false |
Lets several replicas share one Postgres database, and needs a postgres:// connection string. |
ha.replica_idHA_REPLICA_ID |
the hostname | A stable name per replica, which labels the sandboxes it creates. |
ha.actors.hostHA_ACTORS_HOST |
127.0.0.1 |
The address other replicas reach this replica at. |
ha.actors.portHA_ACTORS_PORT |
7571 |
The UDP port of the connections between replicas. |
High availability walks through a complete setup.
Advanced options
Section titled “Advanced options”Most installs leave these alone.
app.env(APP_ENV), defaultproduction. Keep it. Withdevelopmentortest, Umpteenth starts without an encryption key and uses a built-in, insecure one.sandbox.adapter(SANDBOX_ADAPTER), defaultdocker, which drives Podman as well.nonestarts Umpteenth without a sandbox backend.sandbox.broker_host(SANDBOX_BROKER_HOST) applies when you run theumpteenthbinary on a host instead of in a container. A relay container then forwards sandbox traffic to this address,host.docker.internalby default andhost.containers.internalon Podman.ha.actors.bind_address(HA_ACTORS_BIND_ADDRESS) is the interface the peer connections listen on. It defaults to every interface with HA and toha.actors.hostwithout.