Server (harnessd)

Server secrets

Give harnessd its model, tracker and push credentials in secrets.env, per-project files, or the write-only overlay admins change from the app.

harnessd reads secrets from files you control on the server, plus an overlay that admins change from the app. Values set from the app are write-only: only names ever come back.

Where values come from#

LayerWhereScope
secrets_file/etc/harness/secrets.env, mode 0600Server-wide
projects[].secrets_fileFor example /etc/harness/projects/<name>.env, mode 0600One project, overriding server-wide values
The overlaydata_dir/secrets/remote.json, mode 0600 (directory 0700)Server-wide and per project, set by admins from the app

An overlay value wins over the file's value with the same name. Removing it from the app falls back to the file's. The files are never rewritten.

secrets.env#

The file is KEY=VALUE lines. # starts a comment, a leading export is allowed, and values may be wrapped in single or double quotes.

/etc/harness/secrets.env
# chmod 600, owner harness. Never commit the real file.

# Agent / model credentials: injected only into agent processes, never into hooks or $VAR resolution.
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat…
# ANTHROPIC_API_KEY=sk-ant-api…
# OPENAI_API_KEY=sk-…
# HARNESS_GATEWAY_API_KEY=sk-…        # LiteLLM virtual key (give it a budget)

# Tracker credentials referenced from WORKFLOW.md as $VAR (resolved host-side, stripped from agents):
CLICKUP_API_TOKEN=pk_…
# GITHUB_TOKEN=github_pat_…

# Branch publishing (git push + gh pr create at hand-off), and cloning https projects added from the app.
# Host-only; stripped from every agent and hook environment. Use a fine-grained token limited to the
# project repos with Contents: read/write and Pull requests: read/write. Requires `gh` for PRs.
HARNESS_GITHUB_TOKEN=github_pat_…
# HARNESS_GITLAB_TOKEN=glpat-…

# Cloudflare sandboxes: the bridge Worker's HARNESS_BRIDGE_TOKEN. Host-only; never passed to agents.
# HARNESS_CLOUDFLARE_TOKEN=…

# Anything else is a variable for $VAR references and hooks:
SENTRY_DSN=https://…
Shell
sudo chown harness:harness /etc/harness/secrets.env
sudo chmod 600 /etc/harness/secrets.env
sudo systemctl restart harnessd

harnessd check fails if the file is readable by group or others.

How each kind of name is used#

NamesUsed forReaches
ANTHROPIC_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, OPENAI_API_KEYAgent credentialsThe egress proxy's relay, in memory; sandboxes get a placeholder
HARNESS_GATEWAY_API_KEY, LITELLM_API_KEYGateway keyThe egress proxy's relay, in memory; sandboxes get a placeholder
HARNESS_GITHUB_TOKEN, HARNESS_GITLAB_TOKENPush, PRs, cloningThe server's own git, through a credential helper
HARNESS_CLOUDFLARE_TOKENThe bridgeThe server only
Everything else$VAR in WORKFLOW.md, hooks, docker.envHooks; sandboxes only for names in docker.env (model credentials never)

Every value of 8 characters or more is redacted from anything the server hands out: transcripts, run errors, container logs, connection-test errors.

Change secrets from the app#

  1. Open Server Settings or the project's secrets

    For server-wide values: the server's Server Settings → Credentials (model keys) or Environment (any variable). For one project: the project's … menu → Project Secrets & Test Logins….

  2. Set, replace or remove

    Rows show only names and where each comes from: file or set from the app. Fields start empty; typing a value replaces it. Remove… removes a value set from the app, falling back to the file's.

  3. Enter a code

    Every change asks for a fresh code from your authenticator. In Server Settings, one code covers a whole Save. Changes are audited by name, never by value.

Values must be one line, up to 16 KB. Names are environment-variable names: letters, digits and _, starting with a letter or _, up to 128 characters.

After a change, every project reloads its workflow, so $VAR references and credentials pick up the new value without a restart.

See also#