Skip to content

Configuration reference

Every setting of a Core installation has exactly one home. There are two kinds:

KindExamplesHomeChange it withTakes effect
Process settingsPublic URL, ports, logging, harnesses, execution concurrency, audit retention, OAuth origins, database pool, Runtime history exportconfig.json in the installation directory (default ~/.oac/core)Web domain setup or oac domain for managed HTTPS; otherwise edit the file, then run oac applyoac apply restarts the services that read the changed settings
Runtime settingsSandbox backend and size, nodes, Projects and keys, default models, executor credentialsCore's PostgreSQL databaseWeb, or the Core API (/core/v1) with the Core keySaved without a Core restart; nodes prepare Runtime changes asynchronously

Web's System page shows the installation's addresses, the default models, the sandbox configuration and, under Startup settings, the process settings read-only with the path of config.json and the apply command. Secrets live in secrets/, one copy each. The files in generated/ are derived from config.json. No configuration file defines Projects or API keys.

Process settings: config.json ​

The installer writes every setting that applies to the installation's mode, so the file shows each value. Installer flags listed in installation options only seed it. To change a setting, edit the file and apply it:

sh
~/.oac/core/oac apply --dry-run   # show the changed settings, files and restarts
~/.oac/core/oac apply

How oac apply works ​

  1. It validates config.json and changes nothing if a value is invalid. mode, native_core and ingress are fixed after installation; to change them, install into a new directory. It also checks the listeners that a changed host, port or managed-ingress public_url adds (ports), and changes nothing if host is not an address of this machine or another program holds one of their ports; the installation's own listeners do not count.
  2. It writes the files Core, Web and Compose read into generated/: compose.json, core.env, core-key-digests.json, settings.json and, when used, runtime-history.json, the managed Caddyfile and the native Core unit. Don't edit them. A generated file edited by hand stops apply until you move the change into config.json and run oac apply --discard-edits, which keeps the edited copy as generated/<file>.edited-<time>.
  3. It compares what it wrote with what actually runs. Each container carries a digest of its inputs (the io.oac.inputs label; native Core carries OAC_INPUTS), and apply recreates or restarts exactly the services whose inputs differ: Core first, then Web. The Restarts column below says which services a setting affects; see stop and restart for what a restart interrupts.
  4. While any service runs, apply also starts the stopped ones. After oac stop, it only writes the files and the installation stays stopped.
  5. If Core refuses a value at startup, apply prints Core's startup error. If every service was running with the previous files, it restores them and starts the services again; otherwise it reports the failure, and the next apply finishes the work.

oac status reports changes to config.json that are not applied yet and generated files edited by hand.

Changing the public URL ​

public_url is the one origin that applications, nodes, sandboxes and self-hosted executors use. Core derives the daemon WebSocket URL, the self-hosted remote_url and each sandbox's connection address from it. With null, Core uses its loopback origin. Until public_url is set, a managed installation serves only Web, over HTTP on the host's IP address at ports.web; afterwards that address redirects to public_url.

With managed ingress, change it in Web (System → Configure domain and HTTPS) or with oac domain HOSTNAME. Both take the installation lock, verify the new certificate and address, then write config.json and apply it. With external ingress, update your reverse proxy first, then edit public_url and run oac apply.

When nodes, hosted sandboxes or self-hosted executors are bound to the current address, apply lists them and asks you to type the new URL (--confirm-public-url-change URL without a terminal). Afterwards:

  • Nodes on the old address get no new sandboxes: remove them in Web and add them again.
  • Existing sandboxes and executors keep working only while the old address still reaches this Core. A managed domain change replaces the previous domain route.
  • Self-hosted executors must restart with the new remote_url, and their installer refuses an installation made for the old address: create new self-hosted Sessions and connect their hosts again.

Settings ​

core.runtime_history.headers may hold export credentials. They stay in the 0600 config.json and the generated file Core reads, and never appear in oac output or in Core's settings snapshot. Model providers are not process settings; see Default models.

KeyTypeDefaultModesChangeRestartsMeaning
$schemastringnoneallany timenoneEditor hint that points at the installed copy of this schema. Ignored.
format1noneallfixednoneConfiguration format for this release. Fixed after installation.
mode"all" | "core-only" | "web-only""all"allfixednoneWhich services this installation runs.
native_corebooleanfalseall, core-onlyfixednoneRun Core as a systemd user service instead of a container.
public_urlstring or null (canonical origin; HTTP only on loopback)nullalloac applycore, webCanonical public origin of Core and Web. With managed ingress, set the DNS hostname in Web or run oac domain; certificates are automatic. With external ingress, configure your TLS reverse proxy before applying this value.
hoststring (IPv4 or IPv6 address)"127.0.0.1"alloac applycore, webListener IP. With managed ingress only the gateway is public; Core stays on loopback. The default combined installer listens on all IPv4 interfaces.
ports.coreinteger 1024–655358091all, core-onlyoac applycore (core, web with native Core)Host port of the Core API. With native Core, Web follows it.
ports.webinteger 1024–655358080all, web-onlyoac applywebHost port of Web.
ports.databaseinteger 1024–65535noneall, core-onlyoac applydatabase, coreLoopback port of PostgreSQL. Present exactly when native_core is true; the installer picks a free port.
web.core_urlstring (canonical origin; HTTP only on loopback)noneweb-onlyoac applywebOrigin of the Core that this Web connects to: HTTPS, or HTTP on a loopback host.
log.level"debug" | "info" | "warn" | "error""info"alloac applycore, webMinimum log level of Core and Web.
log.format"auto" | "text" | "json""auto"alloac applycore, webLog format. auto writes text to a terminal and JSON otherwise.
log.add_sourcebooleanfalsealloac applycore, webAdd the source file and line to each log record.
core.execution_concurrencyinteger 1–10244all, core-onlyoac applycoreConcurrent execution work units in Core. Unrelated to node sandbox capacity.
core.harnessesarray of "claude_sdk" | "codex" | "mcode"["claude_sdk", "codex", "mcode"]all, core-onlyoac applycoreHarnesses that Sessions may select.
core.default_harness"claude_sdk" | "codex" | "mcode""codex"all, core-onlyoac applycoreHarness used when a Session names none. It must be listed in core.harnesses.
core.write_audit_retentionstring (Go duration, at least 1h)"2160h"all, core-onlyoac applycoreHow long non-creation write history is kept, as a Go duration of at least 1h.
core.oauth_trusted_originsarray of string (canonical HTTPS origin)[]all, core-onlyoac applycoreExtra HTTPS origins trusted as private OAuth issuers.
core.database_pool.max_connsinteger or null ≥ 1nullall, core-onlyoac applycoreMaximum database connections. null keeps the driver default, max(4, CPU count).
core.database_pool.min_connsinteger or null ≥ 0nullall, core-onlyoac applycoreMinimum idle database connections. null keeps the driver default, 0.
core.database_pool.max_conn_lifetimestring or null (Go duration)nullall, core-onlyoac applycoreGo duration. null keeps the driver default, 1h.
core.database_pool.max_conn_idle_timestring or null (Go duration)nullall, core-onlyoac applycoreGo duration. null keeps the driver default, 30m.
core.database_pool.health_check_periodstring or null (Go duration)nullall, core-onlyoac applycoreGo duration. null keeps the driver default, 1m.
core.runtime_historyobject or nullnullall, core-onlyoac applycoreRuntime history collection and OTLP export. null keeps local collection with Core's defaults. Core checks the values at startup.
core.runtime_history.transportstringnoneall, core-onlyoac applycoreOTLP export transport: otlp_http. Required with endpoint.
core.runtime_history.endpointstringnoneall, core-onlyoac applycoreOTLP/HTTP metrics URL: a canonical absolute URL with a path and no credentials, query or fragment; HTTPS, or HTTP with insecure. Omit it to keep history local; transport, insecure and headers then must be absent.
core.runtime_history.insecurebooleannoneall, core-onlyoac applycoreExport without TLS. Required for an HTTP endpoint and refused for HTTPS.
core.runtime_history.headersobject of string valuesnoneall, core-onlyoac applycoreHeaders sent with each export, such as credentials. Host, Content-Length, Content-Type and Content-Encoding are refused. Never shown by oac or Core. Sensitive.
core.runtime_history.queue_capacityintegernoneall, core-onlyoac applycoreCapacity of the history write queue and of the export queue, up to 4096. Omitted or 0 selects 256.
core.runtime_history.timeout_secondsintegernoneall, core-onlyoac applycoreHistory write, export and query timeout in seconds, up to 30. Omitted or 0 selects 2.
core.runtime_history.sample_interval_secondsintegernoneall, core-onlyoac applycorePeriodic sampling interval in seconds, 5 to 300. Omitted or 0 selects 30.
ingress"managed" | "external""external"allfixednonemanaged provides automatic HTTPS and Web domain setup for a combined Docker installation; install.sh selects it by default. external uses your existing proxy. Fixed after installation.
//: # (END config-reference)

The schema is deploy/install/config.schema.json; each installation keeps a copy in generated/config.schema.json for editors. Core serves the non-secret settings snapshot, with the path of config.json and the apply command, at GET /core/v1/installation. How Core collects and keeps Runtime history is in retained history.

Runtime settings: Web ​

Runtime settings live in Core's database. Change them in Web; scripts use the same Core API with the Core key.

SettingWhere in WebCore APINotes
Sandbox backend: Docker, microsandbox or E2BSystem → Manage sandbox configuration: the setup wizard, ending with Save configuration/core/v1/sandbox/deploymentOne backend per installation. install.sh --sandbox saves the first choice. Another backend needs Reset deployment first; see change the sandbox configuration
Sandbox size, Runtime release, E2B key and template buildSystem → Manage sandbox configuration → Change resources/core/v1/sandbox/deploymentWeb proposes the sizes in standard-sizes.json. Existing sandboxes keep their size and release. The E2B key is write-only and encrypted
Nodes and their capacityNodes: Add node; Edit node and Remove node on a node's page/core/v1/sandbox/enrollment-tokens, /core/v1/sandbox/nodesSee Node capacity and the nodes guide
Projects and API keysProjects and keys: Create project, Rename, Issue key, Revoke, Archive/core/v1/projectsKeys are shown once; Core stores digests
Default model per harnessSystem → Default model configuration: Set/core/v1/harnesses/{harness}/model-configurationSee Default models
Executor credentials of a self-hosted SessionSession log, then the Session page: Executor credentials/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentialsSee self-hosted executors

Which harnesses are enabled, and the default one, are process settings (core.harnesses, core.default_harness); System shows them read-only. The Core administration API lists every Core API route, and the deployment contract defines the sandbox fields, limits and change rules.

Node capacity ​

Core approves a node's capacity when you generate its Add node command: Sandboxes at once (max_active, default 2) and, for microsandbox only, Retained sandboxes (max_retained, default 8), with max_retained >= max_active >= 1. Docker never suspends sandboxes, so Web doesn't ask for it and Core keeps max_retained equal to max_active. Change them later with Edit node. Reservations and cleanup that is not confirmed count against capacity; lowering a limit stops no running sandbox. A node's own files can't change its capacity, size or Runtime.

core.execution_concurrency is unrelated: it limits concurrent execution work in Core.

Default models ​

Set a default in System → Default model configuration, or use PUT /core/v1/harnesses/{harness}/model-configuration. Core encrypts provider keys with secrets/credential.key and never returns them. Model execution owns the request fields and replacement rules, and precedence says which Sessions use a default.

Compose installations ​

The standalone Compose template uses its Compose definition and the platform's environment as the source of process settings. An unset or empty OAC_PUBLIC_URL selects http://localhost:8080, allowing startup before a public domain is configured. Core and Web receive that same value. For public access, set OAC_PUBLIC_URL to the exact public HTTPS origin without a trailing slash and redeploy Core and Web with the same project and volumes; changing an environment variable requires container recreation, not just a restart. Configure the public origin before adding nodes or executors. The platform owns TLS and routes to gateway:8080; Web's installer-managed domain setup is unavailable.

The initialization service generates secrets and the installation ID once, then verifies them on subsequent deployments. Each secret has one persistent source; Core's key digest is derived from Web's sign-in key. Initialization never replaces missing or changed secrets on an existing installation. Core reads its existing process environment and file settings, so the installer-specific config.json, oac apply and startup settings snapshot do not apply to this deployment.

Compose volumeContentReaders
databasePostgreSQL dataPostgreSQL; initialization checks whether it is empty
database-secretGenerated database passwordPostgreSQL, migrator and Core
core-configCredential encryption key, installation ID, Core key digest and initialization receiptMigrator and Core
web-secretGenerated Core sign-in keyWeb and the explicit credentials tool
core-statePrivate Provider stateCore
node-payloadVerified node installation metadataWeb

Initialization prepares these volumes; application services receive their secret volumes read-only. The credentials tool disables container logging. Retrieve its output only in an operator terminal. Database passwords and credential encryption keys are never printed.

The Compose project name scopes the volumes. Preserve every volume together with that project's definition and public URL. Removing only secret volumes does not reset an installation; initialization refuses to start over an existing database. Core also binds the installation ID to its database. Runtime settings continue to live in Core's database.

Docker node configuration ​

The node installer writes Docker’s provider configuration into the node’s configuration file; these fields are separate from Core’s config.json. Deployment resources, Runtime images and capacity remain in Core’s database.

FieldInstaller valueMeaning
hostunix:///var/run/docker.sockExplicit Docker Engine socket
networkoac-node-<installation-id>Runtime container network
seccomp_file<node-root>/runtime/seccomp.jsonMatched distribution’s seccomp profile
nested_sandboxtrueEnables the Docker adapter’s init process and proc-mask configuration
extra_hostsOptionalAdditional container host mappings

The Docker adapter owns container isolation, volume layout and lifecycle behavior.

Installation directory ​

The installer creates the installation directory, ~/.oac/core by default, with mode 0700; the files in secrets/ are 0600.

PathContentChanged by
config.jsonProcess settings. The only file you editYou, then oac apply; managed domain setup for public_url
oacThe management commandThe installer
state.jsonInstallation ID, Compose project name, image IDs, source commit, the digests of generated files and whether the services have started onceThe tools only
secrets/core.keyThe Core keyoac rotate-core-key
secrets/credential.keyEncryption key for what Core stores sealed in the database: model providers, the E2B key, Vault credentials, Skills, initial files and environment setupNothing. Keep it with the database; oac apply refuses a changed file
secrets/database.passwordPostgreSQL passwordNothing. PostgreSQL reads it only when the database is created; oac apply refuses a changed file
generated/Files derived from config.jsonoac apply
node-payload/The node installer and node files that Web serves at /node-install/, one directory per releaseThe installer
native-installers/Self-hosted daemon installers for each platform, with their catalog, when the bundle carries themThe installer
state/e2b/Private E2B receiptsCore
ingress/Managed HTTPS: certificates and gateway state, domain setup status and the control socketsThe gateway and installation services
native/Core binaries, with native CoreThe installer
.oac.lockThe installation lockThe installer and mutating oac commands

A Web-only installation has only secrets/core.key, a copy of its Core's key, and no state/ or native-installers/. A Core-only installation has no node-payload/. Only managed ingress has ingress/. With native Core, the installation directory and the bundle must be canonical absolute paths without control characters, quotes, backslashes or wildcards.

In Docker, the Compose project is named oac-<10 hex digits> (project in state.json). Its services are database, migrate, core and web, plus gateway and installation with managed ingress. gateway routes to Core and Web and publishes ports.web, plus 80 and 443 once HTTPS is on; installation applies domain changes from Web and uses the Docker socket to do so. The volume <project>_database holds all data. Native Core runs Core as the systemd user unit <project>-core.service instead of a container. Apart from Docker's storage, nothing is written outside your home directory.

Appendix: Core environment without the installer ​

Core reads only its environment. The installer renders generated/core.env from config.json; if you run Core yourself (see the service guide), set these variables. Compose loads the file with env_file and systemd with EnvironmentFile, so Compose must be 2.26.0 or newer.

VariableSet from
OAC_PUBLIC_URLpublic_url, or Core's loopback origin. Core derives the daemon WebSocket URL, the self-hosted remote_url, the hosted sandbox address and the deployment's read-only core_url from it, never from request headers. Without it, Core runs no Runtime gateway and executes no Sessions
OAC_ADDRThe installer derives the native listener from ports.core and sets :8091 in the container. Independently started Core defaults to 127.0.0.1:8091 when unset or empty
OAC_DATABASE_URLThe installation's PostgreSQL without a password, plus core.database_pool as pool_* query parameters
OAC_DATABASE_PASSWORD_FILEsecrets/database.password. The URL must then carry no password; migrations and the maintenance commands read the file too
OAC_CREDENTIAL_KEY_FILEsecrets/credential.key
OAC_CORE_KEY_DIGESTS_FILEgenerated/core-key-digests.json: a JSON array with the SHA-256 of the Core key
OAC_INSTALLATION_IDThe installation ID from state.json, a canonical UUID. It enables the sandbox deployment and node routes and requires OAC_PUBLIC_URL and OAC_CORE_KEY_DIGESTS_FILE. Core refuses an ID other than the one its database recorded, so keep the two together
OAC_SETTINGS_FILEgenerated/settings.json, the snapshot Core serves at GET /core/v1/installation; Core does not act on it
OAC_EXECUTION_CONCURRENCY, OAC_DEFAULT_HARNESS, OAC_WRITE_AUDIT_RETENTION, OAC_OAUTH_TRUSTED_ORIGINSThe matching process settings; omitted or empty default Harness uses core.default_harness’s documented default
OAC_HARNESSEScore.harnesses with the installer. Independently started Core enables only the default Harness when unset; comma-separated explicit names supplement it. Entries are trimmed and deduplicated; unknown names stop startup
OAC_HISTORY_SETTINGS_FILEgenerated/runtime-history.json: the core.runtime_history object, when it is set
OAC_LOG_LEVEL, OAC_LOG_FORMAT, OAC_LOG_ADD_SOURCElog.*; Web reads the same three
OAC_PROVIDER_ROOTAbsolute adapter artifact root: native/ for native Core, /opt/oac in the Core image. Each adapter owns its helper paths beneath this root
OAC_PROVIDER_STATE_ROOTAbsolute private state root: state/ for native Core, /state in the Core image. Each adapter owns its subdirectory; E2B uses e2b/, owned by Core's user with no group or other access. Back it up with the database and credential.key; don't mount it into Web or a Runtime
OAC_NATIVE_INSTALLER_DIRnative-installers/, served to self-hosted machines; the Core image has a copy at /opt/oac/native-installers, used when this is unset. Core checks the catalog against its own release before serving it

Core logs the file paths it loads, never environment values or file contents.

Invalid explicit OAuth trusted origins stop Core at startup. Entries must be HTTPS origins without credentials, query or a non-root path; the installer validates core.oauth_trusted_origins before generating them. Vaults owns refresh and network policy. A private issuer also needs a trusted CA: independently managed Unix Core can use Go’s SSL_CERT_FILE PEM CA-bundle override, which preserves certificate verification. Managed installation has no custom-CA setting or mount; do not edit generated/core.env.

Appendix: Web environment without the installer ​

The installer sets these variables from config.json; set them yourself only when you run the console without the installer. Of the installation's secrets, the installer gives the console only secrets/core.key.

VariableDefaultMeaning
OAC_WEB_ADDR:8080Listener address
OAC_WEB_ORIGINhttp://127.0.0.1:8080The exact browser-facing origin, HTTP or HTTPS, without a path. Host and origin checks use it; HTTPS makes the session cookie Secure
OAC_WEB_UPSTREAMhttp://core:8091Core's origin, HTTP or HTTPS, without credentials, query or path
OAC_WEB_CORE_KEY_FILE/admin/core.keyAbsolute path of a regular file with no group or other permissions, holding the Core key: at least 32 characters, no whitespace, at most 4 KiB
OAC_WEB_DIST/wwwAbsolute directory of the built console; must contain index.html
OAC_WEB_NODE_PAYLOAD_DIRunsetAbsolute path of the matched distribution's node payload (the installer's node-payload/). Unset, /node-install/* is not served and Add node is unavailable
OAC_WEB_INSTALLATION_SOCKETunsetAbsolute path of the installer's domain socket. Unset, domain setup reports unsupported
OAC_WEB_BOOTSTRAP01 accepts literal-IP hosts before a domain is configured. Requires an http:// origin and OAC_WEB_INSTALLATION_SOCKET

Defaults apply when a variable is absent; an explicitly empty value is validated as supplied. An invalid OAC_WEB_* value stops the console at startup with a message naming the variable. The console also reads OAC_LOG_LEVEL, OAC_LOG_FORMAT and OAC_LOG_ADD_SOURCE (Core environment); unknown values fall back to their defaults. Use HTTPS for any browser that is not on the same machine.

Released under the MIT License.