Run your own server
Applies to OML v0.6.x · Status: Stable · Last verified 2026-11-06
Three options, each a larger trust domain: a laptop, one host that people reach over TLS, and a Kubernetes cluster. The settings are in configuration and the profiles in deployment.
1. Start a server on your laptop
You need Docker with compose v2 and the oml CLI (install). Without Docker, the quickstart has a variant that runs the release binaries on your own PostgreSQL.
oml quickstart
In order, it:
- writes
oml/compose.yamlwith the server image pinned to the CLI's version, and an owner-onlyoml/.envwith generated passwords for the database's superuser, owner role and serving role; - runs
docker compose up --detach --wait, published on127.0.0.1:8080only (--portchanges it); - reads the enrollment token from the server's log and claims the server, storing the admin
pair in
oml/credentials, not in your own credentials file; - creates the workarea
crewand issues an agent key intooml/keys/agentand a reviewer key intooml/keys/reviewer, both owner-only; - saves a memory as the agent, approves it as the reviewer and finds it as the agent, and names the step that failed if one does;
- prints the key files,
oml setup claude-code --url http://127.0.0.1:8080 --key-file oml/keys/agentandoml login http://127.0.0.1:8080.
A second run in the same directory is refused as quickstart.exists; a machine without compose
is refused as quickstart.docker; --port frees a taken port. docker compose
--project-directory oml down -v removes the stack and its data
(CLI
reference).
The containers are separated from each other, but anyone with root on the host reads every volume, password and the signing keyring (deployment). Use this for trying OML and for one person's memory, not as a team's server.
2. Run a server for a team over TLS
The quickstart gives no TLS, public address, backups or signing key held apart from the data. For a team on one host:
- Run PostgreSQL 17 or later with the
ltreeandpg_trgmextensions and the two roles the server needs: an owner that migrates and a serving role that owns nothing. The server refuses to start when both URLs log in as one role. The SQL is under run on one host behind TLS. -
Install
oml-server-leadfrom the server archive, verified with cosign, and set the two connection strings:export OML_POSTGRES__OWNER_URL=postgres://oml_owner:...@127.0.0.1:5432/oml export OML_POSTGRES__URL=postgres://oml_server:...@127.0.0.1:5432/oml oml-server-lead -
Claim the server from the host before a proxy exposes it, so nobody else presents the enrollment token first (claim the first admin key).
- Put a reverse proxy with TLS in front of it (the proxy rules).
- For claude.ai and the phone apps, set
oauth.issuerto the public origin and pass the/.well-known/oauth-*paths through (connect claude.ai and the mobile apps). - Back up the database and the keyring together; losing the keyring while the database survives loses the deployment's identity (back up).
- Check it with
oml doctorand/readyz(check that it is healthy).
3. Install on Kubernetes
The chart in deploy/helm/oml runs one server instance under Recreate against an external
PostgreSQL, with its keyring on a claim that helm uninstall keeps. The
Kubernetes guide walks the install.
Every upgrade and restart stops the API until the new instance is ready. The chart runs one
instance: there are no read followers and no cluster mode.
Next steps
Give each agent its own key with oml keys issue-agent --out
(administer a server). Against the quickstart's stack, run it as
OML_CLI_CREDENTIALS=./oml/credentials oml keys issue-agent …, because the quickstart keeps its
admin pair there and not in the file oml login writes.