Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/joseluis-dev/harness-ai/llms.txt

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

All environment variables required for Phase 0 and Phase 0.b are injected at runtime via the Dokploy secrets manager. No variable with a real value is ever committed to the repository. The .env.example file at the repository root and infra/dokploy/env.example serve as operator-facing templates — copy one of them, fill in the values through Dokploy, and discard any local copy before committing.

Environment Template

The following template covers all variables needed to bring up the Phase 0 and Phase 0.b stack. Variables tagged # PHASE 0.b are inert seams in Phase 0 and must not be populated until Phase 0.b work begins.
# =============================================================================
# Phase 2 — Model Gateway (additive on top of Phase 1)
# =============================================================================
# Copy this file to `.env` at the repo root and inject real values via
# Dokploy secrets manager or your local secrets backend.
# NEVER commit a real `.env` file.

# ---------- Server (BFF: apps/harness-core / Astro SSR) ----------
SERVER_HOST=0.0.0.0
SERVER_PORT=4321
# Internal DNS alias defined in docker-compose.{local,prod}.yml.
# The BFF forwards execution/audit reads and writes to this address.
SERVER_RUNTIME_BASE_URL=http://runtime-python:8000

# ---------- Runtime Python (apps/runtime-python / FastAPI) ----------
API_HOST=0.0.0.0
API_PORT=8000
# Worker queue name consumed by the in-process RQ worker supervised by
# `infra/docker/entrypoint.runtime-python.sh` (Phase 0; no sibling worker
# compose service).
API_EXECUTION_QUEUE=executions

# ---------- Data ----------
# harness_db — business, executions, audit_events.
HARNESS_DATABASE_URL=postgresql+asyncpg://harness:harness@postgres:5432/harness_db
# Redis used as RQ broker and operational cache.
REDIS_URL=redis://redis:6379/0

# ---------- Logging ----------
LOG_LEVEL=info
LOG_PRETTY=1

# =============================================================================
# PHASE 1 — Identity connector
# =============================================================================
MCP_IDENTITY_CONNECTOR_URL=http://mcp-identity-connector:9001
MCP_IDENTITY_CONNECTOR_TIMEOUT_MS=3000
IDENTITY_MODE=mock
IDENTITY_CACHE_TTL_S=60
IDENTITY_USERS_FIXTURE=/app/src/mcp_identity_connector/fixtures/users.yaml
IDENTITY_REDIS_TIMEOUT_S=3.0
CONNECTOR_HOST=0.0.0.0
CONNECTOR_PORT=9001

# =============================================================================
# PHASE 2 — Model gateway
# =============================================================================
MODEL_GATEWAY_URL=http://model-gateway:9002
MODEL_GATEWAY_PORT=9002
MODEL_GATEWAY_ALLOW_CLOUD=false
MOCK_MODEL_NAME=mock-1
MOCK_EMBED_DIM=8
MCP_RUNTIME_AUDIT_INGEST_URL=http://runtime-python:8000/internal/audit/ingest

# Phase 2 / PR-2 seam (INERT in PR-1; do not populate yet):
# VLLM_BASE_URL=

# =============================================================================
# PHASE 0.b — reserved seams (INERT in Phase 0; do not populate yet)
# =============================================================================
MCP_AUTH_DATABASE_URL=postgresql+asyncpg://harness_auth:harness_auth@harness-postgres-auth:5432/harness_auth_db
POSTGRES_AUTH_USER=harness_auth
POSTGRES_AUTH_PASSWORD=harness_auth
POSTGRES_AUTH_DB=harness_auth_db

# PHASE 0.b
MCP_AUTH_SERVICE_URL=
# PHASE 0.b
HARNESS_AUTH_DATABASE_URL=
# PHASE 0.b
TOOL_REGISTRY_DATABASE_URL=
# PHASE 0.b
MCP_AUTH_JWKS_URL=
# PHASE 0.b
HARNESS_CORE_OAUTH_CLIENT_ID=
# PHASE 0.b
HARNESS_CORE_OAUTH_CLIENT_SECRET=
# PHASE 0.b
ADMIN_PANEL_OAUTH_CLIENT_ID=
# PHASE 0.b
ADMIN_PANEL_OAUTH_CLIENT_SECRET=
# PHASE 0.b
MCP_READONLY_SQL_OAUTH_CLIENT_ID=
# PHASE 0.b
MCP_READONLY_SQL_OAUTH_CLIENT_SECRET=

# =============================================================================
# Later phases — add as each phase is activated
# =============================================================================
# IDENTITY_CONNECTOR_URL=
# JWT_PUBLIC_KEY_URL=
# MCP_READONLY_SQL_URL=
# N8N_WEBHOOK_SECRET=          # Phase 7+ only
# DOCUMENT_ROOT_PATH=          # Phase 4+

Full Variable Reference

HARNESS_DATABASE_URL and HARNESS_AUTH_DATABASE_URL must point to different databases. They correspond to two separate PostgreSQL instances (postgres for harness_db and postgres-auth for harness_auth_db). Pointing both variables at the same database is a blocked anti-pattern that violates the auth/business separation invariant and will prevent a release from proceeding.

Data Layer

VariableTarget ServiceDescription
HARNESS_DATABASE_URLpostgres (harness_db)PostgreSQL connection string for the business database. Format: postgresql+asyncpg://user:pass@host:port/db. The user must have full DDL rights for migrations; application reads/writes use a scoped user.
HARNESS_AUTH_DATABASE_URLpostgres-auth (harness_auth_db)PostgreSQL connection string for the auth database — a separate PostgreSQL instance. Hosts oauth_clients, oauth_scopes, oauth_tokens, oauth_policies, tool_registry, tool_operations, permissions, agent_permissions, audit_auth_events, tool_execution_logs, and security_events.
TOOL_REGISTRY_DATABASE_URLpostgres-auth (harness_auth_db)Alias for HARNESS_AUTH_DATABASE_URL — same database, different name for clarity. Points to harness_auth_db so tool-registry clients can be wired independently. Authorization state (state, scopes, risk_level, permissions) must not live in the business database.
REDIS_URLredisRedis connection string. Format: redis://host:port/db. Used as the RQ job broker and as the operational cache for rate-limiting, context, and identity.

Centralised Auth

VariableTarget ServiceDescription
MCP_AUTH_SERVICE_URLmcp-auth-serviceInternal URL of the OAuth 2.0 authorisation service. Example: http://mcp-auth-service:8000. Set during Phase 0.b.
MCP_AUTH_JWKS_URLmcp-auth-serviceJWKS endpoint of mcp-auth-service. Example: http://mcp-auth-service:8000/.well-known/jwks.json. The auth-sdk fetches this URL to validate token signatures locally, enabling rotation without redeployment.
HARNESS_CORE_OAUTH_CLIENT_IDharness-coreclient_id of the OAuth 2.0 client registered in oauth_clients for the BFF.
HARNESS_CORE_OAUTH_CLIENT_SECRETharness-coreclient_secret for the BFF OAuth client. Used by the auth-sdk to obtain an access_token via Client Credentials (HTTP Basic on POST /oauth/token) and cache it until near expiry. Never stored in plaintext in the repository.
ADMIN_PANEL_OAUTH_CLIENT_IDadmin-panelclient_id of the OAuth 2.0 client registered for the admin panel.
ADMIN_PANEL_OAUTH_CLIENT_SECRETadmin-panelclient_secret for the admin panel OAuth client.
MCP_READONLY_SQL_OAUTH_CLIENT_IDmcp-readonly-sqlclient_id of the OAuth 2.0 client registered for the read-only SQL MCP server.
MCP_READONLY_SQL_OAUTH_CLIENT_SECRETmcp-readonly-sqlclient_secret for the read-only SQL MCP OAuth client.

Internal Services

VariableTarget ServiceDescription
MODEL_GATEWAY_URLmodel-gatewayInternal URL of the Model Gateway. All LLM inference traffic is routed exclusively through this service; no service calls vllm directly. Example: http://model-gateway:9002.
VLLM_BASE_URLmodel-gatewayvllmInternal URL of the vLLM backend. Consumed by the vllm_local provider inside the Model Gateway. When empty, the gateway returns 503 vllm_unavailable for vllm_local requests.
MCP_READONLY_SQL_URLmcp-readonly-sqlInternal URL of the read-only SQL MCP server. Agents call this URL; they never receive direct database connection strings. SQL credentials are loaded from service environment variables and allowed profiles live in tool_registry.config.
IDENTITY_CONNECTOR_URLmcp-identity-connectorURL of the external identity system or its mock. Consumed by the BFF and the runtime to resolve actor context.

Identity and Sessions

VariableTarget ServiceDescription
JWT_PUBLIC_KEY_URLharness-core (Astro session)JWKS URL for the institutional identity provider. Used to validate session tokens issued to browser clients. Preferred over inlining the public key, as it enables key rotation without redeployment.
MCP_AUTH_JWKS_URLmcp-auth-service(Also listed under Centralised Auth above.) JWKS URL used by the auth-sdk across all internal services to validate signatures locally.

Webhooks and Automation

VariableTarget ServiceDescription
N8N_WEBHOOK_SECRETn8n (Phase 7+)HMAC secret shared with n8n for validating signed webhook payloads. Required only when Phase 7 is active. Must be rotated at least quarterly.

Document Ingestion

VariableTarget ServiceDescription
DOCUMENT_ROOT_PATHdocument-watcher (Phase 4+)Absolute path to the directory observed by the document watcher for new and changed files. Not required until Phase 4 is activated.

Management Rules

Secrets outside the repository

No variable with a real value is ever committed. All secrets are injected via the Dokploy secrets manager or the host environment before docker compose up. The .env.example and infra/dokploy/env.example files contain only placeholders.

Dual-database separation

HARNESS_DATABASE_URL and HARNESS_AUTH_DATABASE_URL must always point to different databases. The auth database isolation is an architectural invariant enforced from the first commit.

Per-environment variable sets

Each environment (dev, staging, prod) has its own complete set of variables. Values are never shared or reused across environments.

Quarterly rotation

OAuth client_secret values for all registered clients (including internal services) and N8N_WEBHOOK_SECRET rotate at least once per quarter, or immediately after any incident. Rotation uses active_secret_hash and previous_secret_hash with a grace window; the auth-sdk re-obtains tokens automatically near expiry.

Fail-fast on missing vars

The harness exits with code 1 on startup if any required variable is unset. There are no insecure defaults. The entrypoint scripts use : "${VARIABLE:?message}" syntax to abort immediately on missing values.

PUBLIC_* vs SERVER_*/API_* prefixes

Variables intended for the browser bundle in the Astro BFF and the admin panel use the PUBLIC_ prefix. Any secret or internal endpoint is named with SERVER_ or API_ and is excluded from the client bundle automatically.
This reference covers Phase 0 + Phase 0.b. Additional variables (for example TELEGRAM_BOT_TOKEN in Phase 8) are documented in their respective phase specifications and added to env.example as inert seams ahead of activation.

Build docs developers (and LLMs) love