The oac command
Each installation has its own management command in its directory. It needs neither the bundle nor root:
For a second installation, use its own command, such as
~/.oac/web/oac status.
Service health
Use these observations for different questions:
Service health does not show that a harness or a model works. Use Session, Turn, Items and Usage reads for execution, and Web’s Nodes page for node connection, readiness and placement. For local diagnosis, use the installation’s own Compose file:
journalctl --user -u <project>-core.service, with project from state.json. Don’t paste docker compose config, docker inspect or raw logs into public issue reports.
Stop and restart
Let active work settle before a planned restart:oac apply, signs everyone out of the console. Web sign-ins otherwise last 12 hours.
Core key
Each installation has one administrator credential, the Core key. The installer generates a 64-character random key in<install dir>/secrets/core.key, by default ~/.oac/core/secrets/core.key. The Core key:
- signs in to Web. The browser gets an HttpOnly session cookie, never the key;
- authorizes Core API (
/core/v1) requests sent asAuthorization: Bearer <Core key>; - never authorizes the Agents API (
/v1). Applications use Project API keys, which in turn can’t call/core/v1.
secrets/ is mode 0700 and its files 0600. Web and, with managed ingress, the installation service read core.key; Core reads only its SHA-256 from generated/core-key-digests.json, which oac apply derives from the key. A Core key has at least 32 characters and no whitespace. Web limits failed sign-ins.
Script the Core API
Run scripts on the Core host against Core’s loopback port. This helper reads the key from its file, keeping it off the command line:
The Core administration API lists every route; errors use the Core error envelope.
Rotate the Core key
config.json has changes that are not applied or a generated file was edited by hand: run oac apply first. It asks for confirmation (--yes skips it), stops Web, writes a new key to secrets/core.key and regenerates the digest file. On a running installation it then restarts Core, starts Web and checks that Core accepts the new key and refuses the old one; a stopped installation only gets the new files and uses the new key at the next oac start. The old key stops working as soon as Core restarts, and every console session ends: sign in again and update your scripts. If the command stops early, secrets/core.key holds the key to use; run oac apply to finish.
A separate Web-only installation keeps its own copy of the key. After rotating, copy secrets/core.key from the Core host into that installation’s secrets/core.key (mode 0600) and run its oac apply. Its oac status reports a key that Core refuses. rotate-core-key refuses to run on a Web-only installation.
Projects and API keys
Create Projects and issue keys in Web, on Projects and keys, or through the Core API. How Projects and keys behave is in Projects own assets. To rotate an application key:- Issue a new key in the same Project.
- Update the application to use it.
- Revoke the old key.
core.write_audit_retention.
Back up
Back up these together; a restore needs all of them:-
the PostgreSQL volume
<project>_database. It holds Projects, key digests, nodes, default models, encrypted credentials and all execution history, including large objects. A logical dump: -
the installation directory:
config.json,state.json(installation ID) andsecrets/.credential.keymust stay with the database, or stored credentials can’t be decrypted; never regenerate it to get past an error. -
state/e2b/, when E2B is used: receipts Core needs to clean up E2B sandboxes. -
each node’s state directory on its host,
/var/lib/oac-node/.oac/nodes/<installation-id>/, with its provider storage: Docker volumes or microsandbox’s store. See when a node host fails for restoring them. - the bundle you installed from, to repair the same release.
Uninstall
secrets/ and the oac command itself. It keeps an image that has a tag or that another container uses, such as one of another installation of the same release, and says so.
All data goes with it: Projects and API keys, Session history, stored credentials and the Core key. The database volume is useless without secrets/, so it is never kept on its own. To keep the data, stop the installation with oac stop instead, or back it up first.
The command lists what it removes and, when Core answers, the registered nodes. Confirm by typing the installation directory, or pass --yes, which a run without a terminal requires. It holds the installation lock and needs only state.json, so it also removes an installation that did not finish installing or lost config.json. It removes the directory last; if it stops part way, run it again.
Uninstall stops no sandbox: node sandboxes keep running on their nodes, and E2B sandboxes keep running, and billing, at E2B. While Core is still up, archive their Sessions or reset the deployment and let it complete; the command shows how many sandboxes Core has in use.
Nodes on other hosts keep running. To uninstall them the usual way, remove them in Web first, as in Remove a node. After oac uninstall their Core is gone: on each node host, run the node uninstall command with --force, using node-install.pyz from the bundle you installed from. oac uninstall prints that command with the installation ID. A Web-only installation removes only Web; its Core keeps its data and nodes.
Installation version policy
An installation runs one release for its whole life. In-place version upgrades and downgrades are not supported. Nothing migrates data between releases. To move to a new release, install it into a new, empty directory, with its own database, Core key and nodes, and add nodes from its Web. Keep the old installation, its data and its nodes until their work is finished. Nodes run the program of the console that added them and are never upgraded in place; Core accepts only nodes that speak its own node protocol. Repair the current release by rerunning./install.sh --install-dir DIR from the exact same bundle; the downloader keeps it under ~/.oac/releases/. Repair reloads missing images, restores the oac command, applies config.json and starts the services. It preserves identity, settings, secrets and history, accepts only --install-dir, and refuses a bundle from another release. An installation the installer never reported as running is not repaired but removed and installed again.
The installer and mutating oac commands hold the same installation lock, .oac.lock, including during repair and interrupted apply recovery. If another command holds it, retry after that command finishes; never remove or replace .oac.lock to get past a busy installation. Reinstallation never deletes another installation’s files, database, Runtime resources or Session history.
Troubleshooting
Exposure and network policy
Web signs administrators in with the Core key, checks the origin of every request, and forwards signed-in
/core/v1 requests to Core with the Core key, which stays on the server. It answers 404 on /v1 and /api/v1 whatever credential a request carries, serves only the non-secret node payload at /node-install/, and has no Docker or KVM access. Machine routes under /api/v1 use their own enrollment and connection credentials. With managed ingress, the installation service applies domain changes through the Docker socket; Web reaches it only over a private Unix socket, and it checks the Core key on every request.
Sandboxes are the isolation boundary (Runtime and outer isolation). Docker sandboxes share the node’s kernel, and a Docker node is root-equivalent on its host; microsandbox gives each sandbox a microVM with an explicit network policy. Core itself has no Docker socket or KVM access.