# Copy to the compose directory as `.env` (chmod 600) and fill in the values # you need; `compose.yaml` loads it via `env_file:`. The retired # orchestra.service EnvironmentFile= path is gone as of 2026-07-31, and the # container has no entrypoint script that sources an env file — compose passes # these in directly. Every var below is read directly from os.Getenv in # cmd/orchestra/main.go and the packages it wires up — grep ORCHESTRA_ in the # repo if this list ever needs re-deriving. # --- Core --- ORCHESTRA_DATA=/var/lib/orchestra/data ORCHESTRA_PORT=9145 # --- Federation worker (set only on a harness host such as workpc) --- # ORCHESTRA_URL=http://homesrv:9145 # ORCHESTRA_WORKER_ID=workpc-opencode # must equal ORCHESTRA_WORKER_HERDR_ID # ORCHESTRA_WORKER_TOKEN= # ORCHESTRA_FEDERATION_ADMIT_TOKEN= # ORCHESTRA_WORKER_HERDR_ID=workpc-opencode # ORCHESTRA_WORKER_HARNESS=opencode # Pane/process backend. Defaults to herdr. tmux is currently supported only # for Claude Code workers; Codex and OpenCode should remain on herdr. # ORCHESTRA_WORKER_BACKEND=herdr # ORCHESTRA_WORKER_HERDR=/home/orchestra/.config/herdr/herdr.sock # With ORCHESTRA_WORKER_BACKEND=tmux, ORCHESTRA_WORKER_HERDR is not used. # A bare value selects an isolated tmux -L socket; an absolute path selects -S. # ORCHESTRA_WORKER_TMUX_SOCKET=orchestra # Optional Claude executable override; defaults to resolving `claude` in PATH. # ORCHESTRA_WORKER_HARNESS_COMMAND=/home/orchestra/.local/bin/claude # ORCHESTRA_WORKER_STATE=/var/lib/orchestra-worker/state.json # ORCHESTRA_GIT_REMOTE=origin # # One worker process can serve several harnesses (several multiplexers and # several agents) by declaring them in a JSON file. The variables above then # describe nothing: each entry carries its own backend and harness. Every # declared harness is a separate federation identity, because the coordinator # authorizes lease calls by comparing the worker id against the lease's harness # id, so each needs its own token and registers separately. # ORCHESTRA_WORKER_HARNESS_CONFIG_FILE=/etc/orchestra/harnesses.json # [ # {"id":"workpc-claude","harness":"claude","backend":"tmux", # "tmux_socket":"orchestra","command":"/home/kami/.local/bin/claude"}, # {"id":"workpc-opencode","harness":"opencode","backend":"herdr", # "herdr":"127.0.0.1:9247"} # ] # Tokens belong in the environment rather than that file. Each id maps to # ORCHESTRA_WORKER_TOKEN_, uppercased with every other character underscored: # ORCHESTRA_WORKER_TOKEN_WORKPC_CLAUDE= # ORCHESTRA_WORKER_TOKEN_WORKPC_OPENCODE= # Each identity keeps its own state file. Set the directory holding them, or a # per-entry "state" path; the default derives one per id next to the worktrees. # ORCHESTRA_WORKER_STATE_DIR=/var/lib/orchestra-worker # ORCHESTRA_WORKER_ID still names the process for the single-harness form, where # it must equal ORCHESTRA_WORKER_HERDR_ID. ORCHESTRA_MACHINE_ID=homesrv # required when the registry has multiple machines # Static project/machine/herdr topology (registry.Load). Required for # routing across more than one machine; validated at startup. ORCHESTRA_CONFIG=/etc/orchestra/config.json # --- Git worktrees (global default; per-project repo/worktree_root in # ORCHESTRA_CONFIG overrides this per project — see registry.Project) --- ORCHESTRA_REPO=/var/lib/orchestra/repo.git ORCHESTRA_WORKTREE_ROOT=/var/lib/orchestra/worktrees # Protocol version fallback for herdrs that don't set "protocol" in # ORCHESTRA_CONFIG. Prefer setting it per-herdr in the config; only use this # if every herdr on the fleet truly matches. #ORCHESTRA_HERDR_PROTOCOL=1 # Hard rotation occupancy threshold (0 < x < 1). Default 0.75 if unset/invalid. ORCHESTRA_OCCUPANCY_HARD=0.75 # Advisory handoff threshold and the harness context window used to turn # per-session token counts into occupancy. Both values are worker-local. ORCHESTRA_OCCUPANCY_SOFT=0.55 ORCHESTRA_CONTEXT_WINDOW=200000 # OpenCode stores per-session token counters in SQLite. This optional override # must point at the worker-local database; the worker persists the resolved # session ID for each lease, never "the latest" session. #ORCHESTRA_OPENCODE_DB=/home/orchestra/.local/share/opencode/opencode.db # --- Providers --- # Local JSONL task ingestion (baseline adapter). #ORCHESTRA_JSONL=/var/lib/orchestra/tasks.jsonl # Gitea issue ingestion + terminal-state reflection. # # Multiple repos (one per project) — preferred if you have more than one # Gitea-backed project. Points at a JSON array of # {project,base_url,owner,repo,token,webhook_secret}; project is the # registry project id ingested tasks are tagged with. Each source gets its # own webhook path: /v1/providers/gitea/webhook/{project}. #ORCHESTRA_GITEA_CONFIG=/etc/orchestra/gitea.json # # Single repo (legacy) — all four required together. Ignored if # ORCHESTRA_GITEA_CONFIG is set. Webhook path is the unprefixed # /v1/providers/gitea/webhook. Ingested tasks are tagged with project = # ORCHESTRA_GITEA_REPO. #ORCHESTRA_GITEA_URL=https://gitea.example.internal #ORCHESTRA_GITEA_TOKEN= #ORCHESTRA_GITEA_OWNER= #ORCHESTRA_GITEA_REPO= #ORCHESTRA_GITEA_WEBHOOK_SECRET= # Human-input reconciliation. When a Gitea source is configured, issue # comments are imported as human decisions immediately before every lease, # and a source that cannot be read refuses the lease instead of letting a # successor resume from an older intent. Set to "off" only to keep leasing # while a source is known down; agents then run without newer comments. #ORCHESTRA_HUMAN_RECONCILE=off # How many consecutive failed turn-boundary reconciles ask the running session # to hand off. Default 3. The successor's pre-lease reconcile then fails closed # while the source is still down, so the task waits instead of running on # intent Orchestra cannot refresh. #ORCHESTRA_RECONCILE_FAILURE_HANDOFF=3 # Base branch for pull requests created by `task pr`. Defaults to master. The # pull request is created or updated for the task branch orchestra/, # never duplicated: a repeated submission refreshes the same review. #ORCHESTRA_PR_BASE=master # Whose words on a submitted pull request may reopen a task. ACTORS is an # allow-list of forge logins; empty trusts anyone not ignored, which is only # safe on a private forge with no bots. IGNORE_ACTORS always loses. Comments at # or before the submission never reopen anything. #ORCHESTRA_REVIEW_ACTORS=kami #ORCHESTRA_REVIEW_IGNORE_ACTORS=gitea-actions,orchestra-bot # --- Delivery (notify-only surfaces) --- # Telegram: both required together. #ORCHESTRA_TELEGRAM_BOT_TOKEN= #ORCHESTRA_TELEGRAM_CHAT_ID= # ntfy: topic required, token/url optional (self-hosted ntfy). This token is # handed *out* to the ntfy server; it is not an inbound credential — see # ORCHESTRA_NTFY_SURFACE_TOKEN below. #ORCHESTRA_NTFY_TOPIC= #ORCHESTRA_NTFY_TOKEN= #ORCHESTRA_NTFY_URL=https://ntfy.sh # --- Bus authorization tokens (bearer auth per surface; a surface with no # token set has no auth requirement — set these once you have real clients) --- #ORCHESTRA_TUI_TOKEN= # Required: the service refuses to start without both. The browser UI's # task, lifecycle and approval controls are session-gated; it no longer # accepts a shared Web bearer token. Generate the bcrypt hash with: # go run ./cmd/orchestra-password ORCHESTRA_WEB_USERNAME=operator ORCHESTRA_WEB_PASSWORD_HASH= # Set when the UI is served over plain HTTP, so the session cookie can be # sent without Secure. Leave unset behind TLS. #ORCHESTRA_UI_INSECURE_COOKIE=1 #ORCHESTRA_MCP_TOKEN= #ORCHESTRA_MAVEN_TOKEN= # The credential an in-pane coding session may hold. It buys read access plus # the three request endpoints (approval, decision-request, deferred) and # nothing else: phase, review, submission, completion and lease changes are # refused for this surface at the endpoint and again at the bus. This is the # ONLY Orchestra credential that may enter an agent pane; the forge, Vikunja, # worker and operator tokens must stay in the worker. #ORCHESTRA_AGENT_TOKEN= # The turn-boundary endpoint's own token (/v1/harness/turn), authenticated in # the handler rather than by the surface gate. #ORCHESTRA_HARNESS_TOKEN= # Inbound bearer tokens for the notify-only surfaces, separate from the # credentials used to *send* (ORCHESTRA_TELEGRAM_BOT_TOKEN, ORCHESTRA_NTFY_TOKEN). # S12: ORCHESTRA_NTFY_TOKEN used to serve both roles, so configuring ntfy # delivery silently minted a valid inbound credential. #ORCHESTRA_TELEGRAM_TOKEN= #ORCHESTRA_NTFY_SURFACE_TOKEN=