config.json
config. is the relay's own configuration file: its port, who may reach
it, the access token, the timers that decide when a turn counts as stuck, and
the optional tunnels and preview lane. oar setup creates it. You edit it by
hand for everything setup does not ask about.
Most of what you set in the web UI is not in this file. See Settings in the web UI and the environment.
Where the file is #
| Install | Path |
|---|---|
| Global install on macOS, Linux and WSL | ~/. |
| Global install on Windows | %APPDATA%\ |
Global install with OAR_ set |
config. in that folder |
| Git checkout | server/ in the checkout |
OAR_ moves the whole state folder of a global install (config,
data and logs); see Where OAR keeps its files.
COPILOT_ points the relay at one file, wherever it is, but
only where the relay is started without oar's own launcher: node server/, or oar copilot (when the file exists). oar setup,
oar start, oar restart and the service always use the install's own
config., whatever the variable says. In a checkout with no
server/, oar copilot creates its file in
~/. instead (%LOCALAPPDATA%\ on
Windows). See Environment variables.
The relay keeps the file readable by its owner only (mode 0600 on macOS and
Linux), because it holds the access token in plain text. Treat a copy of it
like a password.
Who writes it #
oar setupwrites the token,localhostandOnly port, and keeps every other key as it finds it. A file it creates, or one that lacks them, also getspoll,Interval Ms processing(Timeout Ms 600000) andconversation. SeeSession Mode oar setupand first run.- The relay writes
cliwhen you install or update a provider CLI from Settings. It changes only that key. If it cannot read the file as JSON, it refuses to write and keeps the binding for the running process only.Binaries - The relay creates the file when none exists at start-up, with an empty
auth, portToken 3333,localhost,Only: true pollandInterval Ms conversation. It also removes aSession Mode featureskey left over from older releases (see Deprecated, ignored and internal keys). - You, in any text editor.
Editing it by hand #
The file is one JSON object. Keys you leave out take their defaults, and a
nested block such as previews is read as a whole. Edit it, then restart the
relay: the relay reads the file once, at start-up. Nothing a running relay
holds changes when you save the file. Restart with oar restart (global
installs), or with
🌄 Restart web relay in a conversation's ⋯ menu.
- An unknown key is ignored and kept. Setup and the relay's own writes leave it in place.
- Invalid JSON does not stop the relay. It logs
Failed to read config.and runs with the defaults: port 3333, this machine only, and a random token that is new on every start and printed in the log. Your saved token no longer works until you fix the file. A second reader, the one that chooses the data folder, falls back to the default folder. The relay does not touch the broken file.json, using defaults. - A wrong value is handled key by key. The defaults below are what the relay uses when a timer or limit is missing or unusable. The tunnels and the preview lane stay off and log the reason; the relay itself keeps running.
- The command line wins over the file for one run:
--token <value>and--port <number>onnode server/(server. js oar copilotpasses them too;oar startdoes not) overrideauthandToken portand are never saved to the file. A--portthat is not a number from 1 to 65535 is ignored with a warning.
Do not run oar setup on a file that is not valid JSON
oar setup reads a file it cannot parse as missing. It then writes a new
config. over it with a new token, and every other key in the old file is
lost. Fix the JSON first. Keep a copy of a file you edit by hand.
Network and access #
| Key | Type | Default | What it does |
|---|---|---|---|
auth |
string | none: a random token per start | The token every browser, worker and API client signs in with. If it is empty, the relay makes a random one on every start, prints it to its log and does not save it. oar setup writes a stable one. |
port |
number | 3333 |
The HTTP and WebSocket port, a whole number from 1 to 65535. |
localhost |
boolean | true |
true binds the relay to 127. so only this machine reaches it. Any other value, including false, null, 1 and "yes", binds to all interfaces (0.) so your LAN can reach it. Only true and the text "true" (any case) count as on; the default applies only when the key is missing. It does not affect the tunnels below. |
remote |
string | "" |
A path prefix, when a reverse proxy serves the relay under a subpath, for example /. A leading slash is added and trailing slashes are removed. The relay takes the prefix off incoming requests, and puts it into the sign-in cookie's path, the socket path, and the addresses of files and shared links. |
trust |
Express trust proxy value |
"loopback" |
Which proxies may set the X- headers the relay believes. The client address (rate limits, the sign-in lockout, the share access log) and the host and scheme of new share links are read through it, so a direct client cannot forge them. The default suits a proxy or tunnel on the same machine. Use a hop count (1), an address or subnet ("10.), or a list of them when a proxy on another host forwards to the relay (Reverse proxy). |
allowed |
string array | [] |
Added in 0.9.11 Extra browser origins (scheme, host, and a port other than the default, such as "https://) that the live Socket.IO connection accepts besides the relay's own. Needed for a proxy that rewrites the Host header. See Reverse proxy. |
public |
string array | [] |
Hostnames that reach the relay itself. The preview lane refuses a previews. on one of them (also localhost and 127.), so a previewed app never shares a login cookie with the relay. |
tunnel |
string array | [] |
Extra header names that a tunnel's edge adds to traffic. A request that carries cf- or one of these headers cannot reach the session-worker paths (the sockets your own agents' workers use, which only run on this machine). cf- is always on the list. A comma-separated string works too. The names in the environment variable COPILOT_ (comma separated) are added to these; an empty list here does not switch them off. |
push |
string | mailto: |
The contact address the relay sends to push services with Web Push requests (notifications). Set it to a mailto: address of your own. |
shared |
number | 200 |
Most live viewers counted for one shared conversation link. At least 1. When it is reached, the longest-idle viewer is dropped to make room. |
shared |
number | 5000 |
Most live shared-link viewers counted in total, same rule. Never lower than the per-conversation limit. |
For the first connection, the token and LAN access, see first run.
Turns and timers #
| Key | Type | Default | What it does |
|---|---|---|---|
processing |
number, ms | 600000 |
How long a turn may go without a sign of life from its worker before the relay puts it back in the queue. It is not a limit on a turn's length. A value of 0 or less uses the default. See When a turn is stuck. |
max |
number | 5 |
How often one message may be attempted before it fails for good. At least 1. See Requeueing. |
context |
"default" or "bar" |
"default" |
How the composer shows how full the context is, as a line along its top edge. default is a full-width line whose colour moves from green to red as the context fills. bar is the same line growing from the left to the share of context used. Any other value, in any case, is default. |
The max turn duration, the background task timeout and the stall watches are not here: see When a turn is stuck.
Restarts and shutdown #
These shape the planned restart of the relay (🌄 Restart web relay). See Restarts and resume. Each timer takes milliseconds; a value of 0 or less, or one that is not a number, uses the default.
| Key | Type | Default | What it does |
|---|---|---|---|
restart |
number, ms | 45000 |
How long a restart waits for the turn that is running to finish before it gives up with a shutdown- failure. |
restart |
number, ms | 8000 |
How long the relay waits for a graceful stop before it forces the restart. |
restart |
number, ms | 18000 |
How long one attempt waits for the restart or resume phase before it counts as failed (spawn-). |
restart |
number, ms | 20000 |
How long one attempt waits for the sessions to rebind after the restart (rebind-). |
restart |
number, ms | 1000 |
How long the queue stays paused right after a restart reports ready. |
restart |
number | 3 |
How many attempts a restart gets before it is final. At least 1. |
restart |
number array, ms | [1000, 3000, 7000] |
The wait before attempt 2, 3 and so on. When there are more attempts than entries, the last entry repeats. Entries that are not positive numbers are dropped; an empty result uses the default. |
Memory Added in 0.9.19 #
| Key | Type | Default | What it does |
|---|---|---|---|
heap |
number, MB | 60 % of RAM, from 2048 to 8192 | The relay's heap limit, a whole number of at least 512. Every way of starting the relay reads it: oar start, the systemd service, Windows autostart and the CLI extension. It applies from the next start. A value that is not a whole number of at least 512 is ignored with a line in the log; one above the machine's RAM, or above a container's memory limit, is lowered to that. A --max- in NODE_, or on the node command line that starts server., wins. See The relay ran out of memory. |
Workspace and data #
| Key | Type | Default | What it does |
|---|---|---|---|
workspace |
string array | unset | Absolute folders that conversations may start in, together with everything inside them. Unset or empty allows any existing folder. An entry that is not an existing folder is logged and left out. The environment variable COPILOT_ wins when set. See Limiting where chats may start. |
data |
string | data/ beside the server |
Where the database and the relay's lock file live, and Added in 0.9.17 deepseek-, the Claude Code state of DeepSeek chats. A relative path counts from the folder that holds config.. Uploads follow it into uploads/ inside it; only a relay on the default data/ beside the server, without COPILOT_, keeps them in uploads/ beside the server. COPILOT_ wins when set. oar start, oar restart and the Linux systemd service always set it (to ~/., %APPDATA%\, or your own value), so for a relay started that way this key has no effect. It is for a checkout started directly. The Windows startup launcher pins only the config file, not this variable. |
Provider CLIs #
| Key | Type | Default | What it does |
|---|---|---|---|
cli |
object | written by the relay | Paths to provider CLIs, by provider: claude and grok. The relay writes it when an install from Settings resolves a path, and uses it at the next start so the same program is found again. You can set a path by hand. An entry that is not an executable file is logged and ignored. Other names, copilot included, are not used. |
sdk |
string | detected | Path to the Copilot SDK's index.. The search for an installed Copilot CLI is skipped only when sdk and cli are both set. Alone, it also tells the relay where to look for the extension engine's start-up file, next to it. |
cli |
string | detected | Path to the Copilot CLI's runtime entry (app.). Used with sdk. The relay also hands it to the Copilot workers it starts as their CLI program, unless the environment already names one. |
sdk |
string | newest found | An exact version such as 1.. The search for an installed Copilot CLI then accepts only that version. Ignored when sdk and cli are both set. |
These matter where the relay talks to the installed Copilot CLI itself, for
example to import existing Copilot sessions and to list models. The search
looks in the Copilot CLI's package cache (COPILOT_ adds one folder
to search first). See GitHub Copilot.
Previews #
The previews block turns on the preview lane: a second listener on its own
port and hostname that publishes local dev servers and folders. Setup,
hostnames and the front proxy are on the
preview tool's page.
| Key | Type | Default | What it does |
|---|---|---|---|
previews. |
boolean | false |
Turns the lane on. Only true counts. |
previews. |
number | relay port + 1 |
The port of the preview listener. At least 1024, and not the relay's port; 0 picks a free port each start. |
previews. |
string | 127. |
The address the listener binds to. An address that is not loopback needs previews.. |
previews. |
boolean | false |
Allows a previews. that is not loopback. Every preview is then reachable from the network without the front proxy. |
previews. |
string | none | The public http(s) address of the lane. Required when previews are on. Its hostname must differ from the relay's (see public). A trailing slash is removed. |
previews. |
string array | [] |
Hosts, besides this machine, that a port preview may point at, such as the address of a container or VM. |
previews. |
number | 8 |
Most previews at one time for the whole relay. A value that is not a positive whole number uses 8. |
If one of these rules fails while previews are on, the relay logs PREVIEW LANE disabled with the reason, leaves the lane off and keeps running.
These environment variables override the matching keys:
COPILOT_ (1, true, 0, false), COPILOT_,
COPILOT_, COPILOT_ and
COPILOT_ (comma separated).
Tunnels #
Two tunnels can reach the relay from outside your network. They are independent and can run at the same time. Both are off by default, and a managed tunnel that is missing a required value stays off and logs why.
sshTunnel #
A reverse SSH tunnel to a server of yours. See SSH tunnel.
| Key | Type | Default | What it does |
|---|---|---|---|
ssh |
"disabled" or "managed" |
"disabled" |
managed makes the relay run and restart the tunnel. |
ssh |
boolean | false |
While the managed tunnel is not connected, including before it first connects and when a required value is missing, the relay pauses taking messages from the queue. |
ssh |
string | none | The SSH user on the server. Required when managed. |
ssh |
string | none | The server's host name or address. Required when managed. |
ssh |
number | none | The port that opens on the server (1 to 65535). Required when managed. |
ssh |
"loopback" or "public" |
"loopback" |
Whether the remote port is open only on the server itself or on all its interfaces. Independent of localhost. |
ssh |
string | ssh |
The SSH program. Use a name on PATH or an absolute path: a relative path counts from the relay's program folder. |
ssh |
string | none | The private key to use; ~ is expanded. Without it SSH uses its agent or default keys. |
ssh |
boolean | true |
When the remote port is already held, run a cleanup on the server and try again. Only false turns it off. |
ssh |
boolean | false |
As part of that cleanup, also end your own SSH sessions on the server that run nothing. |
ssh |
string | built in | Your own cleanup command to run on the server instead of the built-in one. |
cloudflaredTunnel #
Runs Cloudflare's cloudflared, which you install yourself; OAR ships none. See Cloudflare Tunnel.
| Key | Type | Default | What it does |
|---|---|---|---|
cloudflared |
"disabled" or "managed" |
"disabled" |
managed makes the relay run cloudflared. COPILOT_ overrides it. |
cloudflared |
boolean | false |
While the managed tunnel is not connected, including when a required value is missing, the relay pauses taking messages from the queue. |
cloudflared |
string | none | The token of your own Cloudflare tunnel. Required when managed. COPILOT_ overrides it. |
cloudflared |
string | cloudflared |
The program, as an absolute path or a name looked up on PATH. COPILOT_ overrides it. |
cloudflared |
string array | [] |
Arguments added after cloudflared tunnel run --token <token>. |
Settings in the web UI and the environment #
Settings in the web UI are not in this file. Provider switches and keys,
the model lists, the max turn duration, the background task timeout and feature
flags are stored in the relay's
database, in the data folder. The file holds what the relay needs before the
database opens (the data folder, the port, the token) and facts about the
machine (CLI paths, tunnels). The one thing the UI writes into the file is
cli. Added in 0.9.17 DeepSeek has no key here either: its API key,
base URL and budget are saved from Settings → Providers → DeepSeek into
the database.
Environment variables. The full list is on
Environment variables. Where a
variable exists for a key, the variable wins over the file: COPILOT_
(data), COPILOT_, COPILOT_ and
COPILOT_ (listed in their sections). COPILOT_
is the exception: its names are added to tunnel. The
--token and --port options win over both for one run.
COPILOT_ itself is covered under Where the file is.
An example #
All values are made up. Delete the blocks you do not use.
{
"authToken": "0f3c1a9e-example-token-do-not-copy",
"port": 3333,
"localhostOnly": false,
"remotePath": "",
"trustProxy": "loopback",
"allowedOrigins": [],
"publicHostnames": ["relay.example.com"],
"tunnelMarkerHeaders": ["x-edge-request-id"],
"processingTimeoutMs": 600000,
"maxRequeueRetries": 5,
"contextIndicatorMode": "bar",
"workspaceRootAllowList": ["/home/dev/projects", "/srv/sites"],
"dataDir": "data",
"cliBinaries": {
"claude": "/home/dev/.local/bin/claude",
"grok": "/home/dev/.grok/bin/grok"
},
"restartShutdownTimeoutMs": 45000,
"restartGracefulTimeoutMs": 8000,
"restartSpawnTimeoutMs": 18000,
"restartRebindTimeoutMs": 20000,
"restartReadyCooldownMs": 1000,
"restartMaxAttempts": 3,
"restartRetryBackoffMs": [1000, 3000, 7000],
"previews": {
"enabled": true,
"port": 3334,
"bindHost": "127.0.0.1",
"allowPublicBind": false,
"publicBaseUrl": "https://preview.example.com",
"allowedTargetHosts": [],
"maxLive": 8
},
"sshTunnel": {
"mode": "managed",
"required": false,
"user": "ubuntu",
"host": "vps.example.com",
"remotePort": 4444,
"remoteBind": "loopback",
"identityFile": "~/.ssh/id_ed25519"
},
"cloudflaredTunnel": {
"mode": "disabled",
"token": "",
"binary": "cloudflared",
"extraArgs": []
}
}
Deprecated, ignored and internal keys #
If you find one of these in a file, you can leave it or delete it:
| Key | What it is |
|---|---|
features |
Retired. Feature flags are now stored in the relay's database (Settings → Features). At start-up the relay copies the values it finds here into the database, unless a value is already stored there, and removes the key from the file. |
ssh, cloudflared |
Old form of mode. true means managed, and is read only when mode is not disabled or managed. |
poll |
Written into new files, but the relay does not read it. It has no effect. |
conversation |
isolated or shared. Written into new files. The relay stores the value on each session record and reports it in its status, but nothing in OAR behaves differently for either value. It has no effect for you. |
cli, model |
Used only by a standalone mode that you start by hand (a developer escape hatch; no oar command starts it). The relay you start with oar start ignores model. It reads cli for one thing: the preview lane never picks that port. |
host |
Read only by the programs that connect to the relay (the session workers and the Copilot extension), to build the address they use; the relay's own listener ignores it (see localhost). Leave it out. |