daemon.json file configures the daemon and every ohd command.
Precedence, highest first: command-line flags → environment variables
→ daemon.json → defaults. ohd install <flags> persists the given
flags into the file (an omitted flag keeps its current value), and
ohd restart applies the result — see
Install & service lifecycle.
The file lives at --config → OH_DAEMON_CONFIG → daemon.json
inside the default data dir:
| Platform | Default data dir |
|---|---|
| macOS | ~/Library/Application Support/openheaders-daemon |
| Linux | $XDG_STATE_HOME/openheaders-daemon (fallback ~/.local/state/openheaders-daemon) |
| Windows | %LOCALAPPDATA%\openheaders-daemon |
Fields
| Field | Type | Default | What it does |
|---|---|---|---|
dataDir | string | platform state dir | Root of everything the daemon persists (storage.json, oracle.db, blobs/, logs/). Created if absent. |
bindAddress | string | 127.0.0.1 | 127.0.0.1 (loopback-only) or 0.0.0.0 (LAN). A LAN bind must also declare a protection posture — see the LAN vs TLS decision. |
bindPort | number | 8137 | The sync/HTTP port. Unprivileged ports only (1024–65535). |
logLevel | string | info | Minimum level the daemon logger emits: error, warn, info, or debug. |
trustedProxy | boolean | false | A trusted reverse proxy fronts the daemon: peer identity for auth logs and rate limits comes from X-Forwarded-For. Never enable without a proxy — clients could spoof the header. |
allowedHosts | string[] | [] | Hostnames the daemon answers as, beyond the always-allowed IP literals, localhost, and *.local — e.g. the reverse proxy’s domain. Bare hostnames only. Anything else on browser-facing routes is refused (DNS-rebinding guard). |
allowInsecureLan | boolean | false | Explicit acknowledgment that a 0.0.0.0 bind without a TLS proxy serves tokens and pairing secrets as cleartext. Without it (and without trustedProxy) a LAN bind refuses to boot. |
webRoot | string | the web/ dir beside the daemon | Directory holding the built web app the daemon serves at /. Headless-only when neither is present. |
oidc | object | not set (SSO off) | OpenID Connect login provider — see the fields below and Users, seats & SSO. The client secret can ride the environment variable so it stays out of the file. |
auditRetentionDays | number | 90 | Audit-log retention window in days. One number for every entry; uncapped upward for compliance deployments. |
auditForwarding | object | not set (no outbound) | Audit→SIEM streaming destination — audit rows POST to this collector as JSON batches behind a durable cursor. See the fields below and Observability. |
licenseFile | string | <dataDir>/license.key | License key file location. The file holds the pasteable oh-license. artifact as plain text. |
licenseRefresh | boolean | true | Self-serve license renewal loop. false disables the refresh agent — the air-gapped/no-outbound posture; offline licenses stand it down on their own either way. |
personalSeats | boolean | true | Personal-seat redemption. false refuses user-held individual seat keys at the seat gate, keeping seat growth on the procurement path. |
proxy | object | not set (env mode applies) | How the daemon’s own outbound requests reach the network (distinct from trustedProxy, the inbound posture). See the fields below. |
Flag and environment overrides
Each field’s command-line flag (persisted byohd install) and
environment variable, where one exists.
| Field | Install flag | Env override |
|---|---|---|
dataDir | --data-dir | OH_DAEMON_DATA_DIR |
bindAddress | --bind-address | OH_DAEMON_BIND_ADDRESS |
bindPort | --bind-port | OH_DAEMON_BIND_PORT |
logLevel | --log-level | OH_DAEMON_LOG_LEVEL |
trustedProxy | --trusted-proxy | OH_DAEMON_TRUSTED_PROXY |
allowedHosts | --allowed-host (repeatable) | OH_DAEMON_ALLOWED_HOSTS (comma-separated) |
allowInsecureLan | --allow-insecure-lan | OH_DAEMON_ALLOW_INSECURE_LAN |
webRoot | --web-root | OH_DAEMON_WEB_ROOT |
oidc | — | OH_DAEMON_OIDC_CLIENT_SECRET (secret only) |
auditRetentionDays | — | OH_DAEMON_AUDIT_RETENTION_DAYS |
licenseFile | — | OH_LICENSE_FILE |
licenseRefresh | — | OH_LICENSE_REFRESH |
personalSeats | — | OH_PERSONAL_SEATS |
proxy | --proxy-* (see the ohd options) | OH_DAEMON_PROXY_* (see below) |
The oidc object
| Field | Type | What it does |
|---|---|---|
oidc.issuer | string (required) | The provider’s issuer URL (http(s), no trailing slash). |
oidc.clientId | string (required) | The OAuth client id registered with the provider. |
oidc.clientSecret | string | The client secret; prefer OH_DAEMON_OIDC_CLIENT_SECRET to keep it out of the file. |
oidc.scopes | string[] | Extra scopes to request beyond the defaults. |
oidc.autoProvision | boolean | Create a directory user on first successful SSO login. |
oidc.sessionTtlDays | number | Web session lifetime in days. |
oidc.redirectOrigin | string | Origin the provider redirects back to, when it differs from the request origin (e.g. behind a proxy). |
oidc.providerLabel | string | Label shown on the login button. |
oidc.claimMappings | object | Map an ID-token claim to workspace grants: claimPath plus rules of { value, workspaceId, role } (role: owner, editor, or viewer). |
The auditForwarding object
| Field | Type | What it does |
|---|---|---|
auditForwarding.url | string (required) | The collector endpoint audit batches POST to. |
auditForwarding.headers | object | Extra headers on every batch (e.g. an auth bearer). |
auditForwarding.batchSize | number | Rows per POST. |
auditForwarding.intervalMs | number | Flush interval in milliseconds. |
The proxy object
| Field | Type | What it does |
|---|---|---|
proxy.mode | string | env (default — honor HTTP_PROXY / HTTPS_PROXY / NO_PROXY, curl precedence), manual, or off. PAC and system resolution are not available on this tier. |
proxy.url | string | Manual mode: the proxy to traverse (host:port implies http://). |
proxy.credentialRef | string | Manual mode: vault entry name holding user:password for the proxy — never the value itself. |
proxy.bypassList | string | Manual mode: NO_PROXY-syntax bypass list (host suffixes, host:port, IPv4 CIDR, *). |
Environment variables
EveryOH_* variable the daemon side reads. Secret material is
env-only by design — passphrases and passwords never ride flags or the
config file.
| Variable | What it does |
|---|---|
OH_DAEMON_CONFIG | Path to daemon.json (same role as --config). |
OH_DAEMON_DATA_DIR | Data directory override. |
OH_DAEMON_BIND_ADDRESS | Bind address override. |
OH_DAEMON_BIND_PORT | Bind port override. |
OH_DAEMON_LOG_LEVEL | Log level override. |
OH_DAEMON_TRUSTED_PROXY | 1/0 — reverse-proxy posture override. |
OH_DAEMON_ALLOWED_HOSTS | Comma-separated allowed hostnames. |
OH_DAEMON_ALLOW_INSECURE_LAN | 1/0 — cleartext-LAN acknowledgment override. |
OH_DAEMON_WEB_ROOT | Web bundle directory override. |
OH_DAEMON_OIDC_CLIENT_SECRET | OIDC client secret, layered onto the file’s oidc block (refused without one). |
OH_DAEMON_VAULT_PASSPHRASE | Vault cipher passphrase (value directly). |
OH_DAEMON_VAULT_PASSPHRASE_FILE | Vault cipher passphrase from a secret file (systemd LoadCredential=, compose secrets:). Exactly one of the pair. |
OH_DAEMON_VAULT_NEW_PASSPHRASE | ohd vault rotate only: the passphrase being rotated to. |
OH_DAEMON_VAULT_NEW_PASSPHRASE_FILE | ohd vault rotate only: same, from a secret file. |
OH_DAEMON_AUDIT_RETENTION_DAYS | Audit retention override. |
OH_LICENSE_FILE | License key file location. |
OH_LICENSE_REFRESH | 1/0 — license renewal loop. |
OH_PERSONAL_SEATS | 1/0 — personal-seat redemption. |
OH_DAEMON_PROXY_MODE | Egress proxy mode (off, env, manual). |
OH_DAEMON_PROXY_URL | Egress proxy URL (manual mode). |
OH_DAEMON_PROXY_CREDENTIAL_REF | Vault entry for the egress proxy credential (manual mode). |
OH_DAEMON_PROXY_BYPASS | Egress proxy bypass list (manual mode). |
OH_DAEMON_TOKEN | Paired token for ohd status --verbose (the token-gated /metrics route). |
OH_DAEMON_USER_PASSWORD | ohd user set-password non-interactive input (value directly). |
OH_DAEMON_USER_PASSWORD_FILE | Same, from a secret file. Exactly one of the pair. |
Constants
| Constant | Value |
|---|---|
| Default port | 8137 |
| Free-tier seat limit | 6 active users |
| Audit retention default | 90 days |