Skip to main content

Documentation Index

Fetch the complete documentation index at: https://oxy.tech/docs/llms.txt

Use this file to discover all available pages before exploring further.

Oxy is configured primarily through environment variables. This page covers the full set of variables for production deployments.
1

Create Environment File

Create a .env file to store your environment variables:
touch .env
chmod 600 .env  # Restrict permissions to owner only
Never commit .env to version control. Add it to .gitignore.
2

Set Required Variables

The variables you need depend on your deployment mode.Single-workspace mode (oxy serve --local) — minimal setup:
OPENAI_API_KEY=sk-...
# or whichever model provider you use
Multi-workspace mode (oxy serve) — required:
# PostgreSQL connection string
OXY_DATABASE_URL=postgresql://user:password@host:5432/oxy

# Directory where workspaces are stored
OXY_STATE_DIR=/data/oxy          # defaults to ~/.local/share/oxy

# LLM provider (at least one)
OPENAI_API_KEY=sk-...

# Authentication (at least one method, or leave all unset for no-auth)
MAGIC_LINK_SECRET=any-long-random-string
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

# Instance owner (recommended for team deployments)
OXY_OWNER=admin@example.com
3

GitHub App (multi-workspace only)

To enable importing repositories as workspaces, set up a GitHub App and configure these variables. See the GitHub App Setup guide for step-by-step instructions.
GITHUB_APP_ID=123456
GITHUB_APP_SLUG=my-oxy-app
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"
GITHUB_CLIENT_ID=Iv23liqo62PgXXXXXX
GITHUB_CLIENT_SECRET=abc123...
GITHUB_STATE_SECRET=$(openssl rand -hex 32)  # keep stable across restarts
4

Enterprise Features (optional)

Required only when using oxy serve --enterprise or oxy start --enterprise:
# OXY_OBSERVABILITY_BACKEND=postgres  # auto-detected; set explicitly to override
Observability uses the existing OXY_DATABASE_URL Postgres connection by default.
5

Verify and Restart

# Check that the variables are loaded
printenv | grep OXY_

# Restart the Oxy service
sudo systemctl restart oxy
sudo systemctl status oxy

Full Variable Reference

Core

VariableRequiredDefaultDescription
OXY_DATABASE_URLRequired (multi-workspace)PostgreSQL connection string
OXY_STATE_DIRNo~/.local/share/oxyDirectory for workspaces and runtime data
OXY_OWNERNoEmail address granted Owner role on login. Owners can promote other users to Admin. When unset, all users are admin (single-user default).
OXY_API_URLNoderived from requestBase URL of the API (set when frontend and backend are on different domains)

Authentication

VariableRequiredDescription
MAGIC_LINK_SECRETFor magic-link authSecret used to sign magic-link tokens
GOOGLE_CLIENT_IDFor Google OAuthOAuth 2.0 client ID from Google Cloud Console
GOOGLE_CLIENT_SECRETFor Google OAuthOAuth 2.0 client secret
OKTA_CLIENT_IDFor Okta OAuthOkta application client ID
OKTA_CLIENT_SECRETFor Okta OAuthOkta application client secret
OKTA_DOMAINFor Okta OAuthYour Okta domain (e.g. company.okta.com)
See Authentication for setup instructions.

GitHub App

VariableRequiredDescription
GITHUB_APP_IDFor GitHub importNumeric App ID from the GitHub App settings page
GITHUB_APP_SLUGFor GitHub importApp slug (appears in the app’s GitHub URL)
GITHUB_APP_PRIVATE_KEYFor GitHub importFull RSA private key PEM block
GITHUB_CLIENT_IDFor GitHub importOAuth Client ID from the app settings
GITHUB_CLIENT_SECRETFor GitHub importOAuth Client Secret from the app settings
GITHUB_STATE_SECRETFor GitHub importRandom secret for HMAC-signing OAuth state and selection tokens
See GitHub App Setup for a full walkthrough.

Enterprise (Observability)

VariableRequiredDescription
OXY_OBSERVABILITY_BACKENDNoStorage backend: auto-detected (postgres if OXY_DATABASE_URL set, else duckdb)
OXY_SERVICE_NAMENoService name for spans (default: oxy)
OXY_OBSERVABILITY_LOG_LEVELNoLog level for observability layer (default: debug)

Tuning

VariableRequiredDefaultDescription
OXY_WORKER_MAX_INFLIGHTNo16Max concurrent tasks executed by a single worker process. Caps wide fan-outs (loops, parallel delegations, consistency runs) so a 1000-iteration loop can’t stampede the database/LLM providers. Per-worker by design — the global ceiling scales with the number of worker processes.

Task dispatch (matcher)

Workflow workers learn about new tasks via Postgres LISTEN/NOTIFY — Oxy does not deploy a separate dispatch service. Each app instance opens one dedicated Postgres connection for its listener (in addition to the main connection pool); plan accordingly when sizing your DB max_connections. Most deployments need no extra tuning. Both authentication modes are supported:
  • Password auth (OXY_DATABASE_URL): the listener parses the URL once at startup and reuses the parsed Config on every reconnect.
  • IAM auth (RDS, OXY_DATABASE_AUTH_MODE=iam): the listener mints a fresh SigV4 token on every (re)connect via the same rds-db:connect IAM permission already required for the connection pool. No additional IAM policy beyond what the pool needs. There is no background token-refresh loop — the listener holds one connection at a time, and Postgres doesn’t re-auth mid-stream, so a token only matters at connect time.
Failure modes degrade gracefully: if the listener connection drops, the reconnect loop re-establishes within seconds (200 ms → 5 s exponential backoff). A 5-minute keepalive ping (SELECT 1) keeps NAT / ELB / PgBouncer / RDS-side idle-timeout policies from silently dropping the connection during quiet periods. Workers also run a backstop poll every 10 seconds so a missed notification turns into bounded latency, not lost work. For monitoring, a 60-second self-NOTIFY health probe fires on the oxy_health_probe channel from every app instance and is heard by every listener (own instance + peers). Each receipt emits a router.health_probe_received tracing event and updates an in-memory last_probe_received_at timestamp. The intended alert shape is absence of the event over a 3-minute window — that catches the failure mode where the connection looks healthy (keepalive succeeds) but the NOTIFY delivery path is silently stuck. The router.notification.delivered trace event from the task channel gives the same signal under load; the probe is what covers naturally-quiet deployments. Repeated router.reconnect warnings within a minute are an independent real signal. A second background loop runs the stale-claim reaper every 30 s to free tasks held by workers that died without cleanup (OOM, panic, network partition). Combined with the default 60 s visibility_timeout_secs on claims, a dead worker’s tasks reappear in the queue within ~90 s. There is no env knob for these intervals yet; they are tuned for healthy steady-state behaviour and rarely need adjustment.

Using AWS SSM Parameter Store

For cloud deployments, fetch secrets from SSM at startup:
# Fetch a single parameter
export OXY_DATABASE_URL=$(aws ssm get-parameter \
  --name "/oxy/database-url" \
  --with-decryption \
  --query "Parameter.Value" \
  --output text)

# Fetch and source a full .env file stored in SSM
aws ssm get-parameter --name "/oxy/env" --with-decryption \
  --query "Parameter.Value" --output text > .env