Configuration Reference
All backend configuration is handled by Pydantic Settings with the BEHAVRY_ prefix (backend/behavry/config.py). Values can be set via environment variables or a .env file in the backend/ directory. The field name maps to the env var by upper-casing and prefixing — e.g. db_url → BEHAVRY_DB_URL.
At startup Behavry warns about any BEHAVRY_* environment variable that doesn't map to a known setting (e.g. a typo like BEHAVRY_ADMIN_PASWORD). Such keys are ignored, not applied — watch the boot logs if a setting doesn't seem to take effect.
Environment
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_ENV | development | No | development or production. Controls JWT auto-generation and the production guards on admin password / JWT keys. |
BEHAVRY_DEBUG | false | No | Enable verbose debug logging. |
Database
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_DB_URL | postgresql+asyncpg://behavry:behavry@localhost:5432/behavry | Yes | Async PostgreSQL connection string. Must use the asyncpg driver. On a multi-tenant deployment the role here must be neither a superuser nor BYPASSRLS, or row-level security is silently skipped. See Multi-Tenant Architecture. |
BEHAVRY_DB_POOL_SIZE | 20 | No | SQLAlchemy connection pool size. |
BEHAVRY_DB_MAX_OVERFLOW | 40 | No | Max connections above pool size during bursts. |
OPA Policy Engine
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_OPA_URL | http://localhost:8181 | No | OPA sidecar base URL. |
BEHAVRY_OPA_TIMEOUT_SECONDS | 2.0 | No | Per-request timeout for OPA calls — this is in the agent's critical path, keep it low. |
BEHAVRY_OPA_FAIL_CLOSED | true | No | If true, OPA unreachability causes a deny (safe default). Set false only for testing. |
JWT & signing keys
| Variable | Default | Required in Prod | Description |
|---|---|---|---|
BEHAVRY_JWT_PRIVATE_KEY | (auto-generated in dev) | Yes | RS256 private key PEM, used to sign agent tokens. Generate with openssl genrsa -out private.pem 4096. |
BEHAVRY_JWT_PUBLIC_KEY | (derived from private if unset) | No | RS256 public key PEM. If only the private key is set, the public key is derived from it. |
BEHAVRY_JWT_ALGORITHM | RS256 | No | JWT signing algorithm. Do not change. |
BEHAVRY_JWT_ISSUER | behavry | No | JWT iss claim. |
BEHAVRY_JWT_ADMIN_KEY | (falls back to JWT_PRIVATE_KEY) | No | Admin-token signing key, shared across the control plane and all data planes so a super-admin JWT minted on any plane verifies everywhere. Agent tokens keep using JWT_PRIVATE_KEY (per-plane isolation). |
BEHAVRY_AUDIT_SIGNER_PRIVATE_KEY | (auto-generated + persisted in dev/lab) | Yes | Base64 32-byte Ed25519 seed for detached audit-event signatures (Sprint FE2-01). |
BEHAVRY_AUDIT_SIGNER_KID | (derived from public key) | No | Names the audit signer key. |
BEHAVRY_AUDIT_SIGNER_PERSIST_PATH | /tmp/behavry-audit-signer.json | No | Where an auto-generated signer key is persisted so the chain survives restarts. |
BEHAVRY_APP_SECRET_KEY | (random at startup) | No | Application secret. Set explicitly for multi-instance deployments. |
Generating JWT keys:
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -out public.pem
export BEHAVRY_JWT_PRIVATE_KEY="$(cat private.pem)"
export BEHAVRY_JWT_PUBLIC_KEY="$(cat public.pem)"
Admin auth & auth provider
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_ADMIN_USERNAME | admin | No | Username for the default tenant admin created on first run. |
BEHAVRY_ADMIN_PASSWORD | (empty) | Yes in prod | Password for the default admin. Production refuses to start if this is empty or a weak default (admin / changeme / password). |
BEHAVRY_AUTH_PROVIDER | password | No | Auth backend: password, clerk, or oidc. |
Clerk (when BEHAVRY_AUTH_PROVIDER=clerk)
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_CLERK_SECRET_KEY | (empty) | Yes | Clerk backend secret (sk_live_... / sk_test_...). |
BEHAVRY_CLERK_PUBLISHABLE_KEY | (empty) | No | Clerk publishable key (informational in the backend). |
BEHAVRY_CLERK_ISSUER | (empty) | Yes | Clerk issuer URL, e.g. https://clerk.your-instance.clerk.accounts.dev. |
Generic OIDC (when BEHAVRY_AUTH_PROVIDER=oidc)
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_OIDC_JWKS_URI | (empty) | Yes | JWKS endpoint, e.g. https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys. |
BEHAVRY_OIDC_ISSUER | (empty) | Yes | Token issuer, e.g. https://login.microsoftonline.com/{tenant}/v2.0. |
BEHAVRY_OIDC_AUDIENCE | (empty) | No | Expected aud claim. Leave empty to skip the audience check. |
The React dashboard reads VITE_CLERK_PUBLISHABLE_KEY and the docs site reads CLERK_PUBLISHABLE_KEY at build time — both should point at the same Clerk project.
URLs & CORS
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_PUBLIC_URL | http://localhost:8000 | No | Public URL of this backend. Baked into provisioning config snippets so generated MCP configs point agents at the right host. |
BEHAVRY_DASHBOARD_URL | https://app.behavry.ai | No | Public URL of the dashboard SPA. Used to build user-facing links (e.g. invite-accept) that must land in the SPA. |
BEHAVRY_CORS_ORIGINS | localhost:3000, localhost:5173, behavry.ai, www.behavry.ai, app.behavry.ai | No | Comma-separated allowed CORS origins. Every new dashboard subdomain must be added here. (app.behavry.ai and the ops dashboard are always allowed.) Also accepts the legacy alias BEHAVRY_CORS_ORIGINS_STR. |
BEHAVRY_RATE_LIMIT_ALLOWLIST | (empty) | No | Comma-separated IPs/CIDRs that bypass IP-based auth rate limiting (e.g. trusted operator IPs). Matched against X-Forwarded-For. |
Browser-extension distribution
| Variable | Default | Description |
|---|---|---|
BEHAVRY_EXTENSION_VERSION | 0.1.8 | Current extension version the "Get extension package" CTA serves. |
BEHAVRY_EXTENSION_BUILD_SHA | d27517c | Build SHA pinned for the download redirect (no latest alias on S3). |
BEHAVRY_EXTENSION_DOWNLOAD_BASE | https://downloads.behavry.ai/extension | Base URL for signed extension builds. |
AI features & model proxies
| Variable | Default | Description |
|---|---|---|
BEHAVRY_AI_ENDPOINT | (empty) | LLM API URL for AI-assisted policy generation (Sprint PW). Empty disables the feature. |
BEHAVRY_AI_API_KEY | (empty) | API key for the AI-assisted policy LLM. |
BEHAVRY_AI_MODEL | claude-sonnet-4-20250514 | Model identifier for AI-assisted policy generation. |
BEHAVRY_OLLAMA_URL | http://localhost:11434 | Upstream Ollama server for the Ollama API proxy. |
BEHAVRY_AI_INFER_URL | (empty) | Central SLM inference service (ai.behavry.ai). Empty = data-plane callers fall back to heuristics / templates. |
BEHAVRY_AI_INFER_TIMEOUT_S | 5.0 | Timeout for central SLM inference calls. |
BEHAVRY_AI_INFER_OLLAMA_URL | http://localhost:11434 | When this process is the inference server, the local Ollama daemon it serves from. |
BEHAVRY_AI_INFER_DEFAULT_MODEL | phi3.5-mini | Default model for the inference service. |
BEHAVRY_AI_INFER_RATE_LIMIT_PER_MIN | 60 | Per-tenant inference requests/min cap. 0 disables. |
BEHAVRY_NEMOCLAW_URL | (empty) | Upstream URL for the NVIDIA NeMo (NemoClaw) proxy. Empty disables it. |
BEHAVRY_OPENSHELL_URL | (empty) | Upstream URL for the NVIDIA OpenShell proxy. Empty disables it. |
BEHAVRY_PF_ENDPOINT | (empty) | Privacy Filter inference service URL. Empty = PF disabled, proxy runs regex-only DLP. |
The Anthropic, OpenAI, and Gemini proxies use the standard provider base URLs and pick up credentials per-request from the client.
Webhooks
| Variable | Default | Description |
|---|---|---|
BEHAVRY_WEBHOOK_URL | (empty) | Comma-separated outbound webhook URLs (Slack, Teams, SIEM, etc.). |
BEHAVRY_WEBHOOK_SECRET | (empty) | HMAC-SHA256 signing secret, sent in the X-Behavry-Signature header. |
BEHAVRY_WEBHOOK_MIN_SEVERITY | high | Minimum alert severity to deliver: low, medium, high, critical. |
BEHAVRY_WEBHOOK_FORMAT | json | Payload format: json or cef. |
Data protection & SIEM encryption
| Variable | Default | Required | Description |
|---|---|---|---|
BEHAVRY_LOCAL_ENCRYPTION_KEY | (empty) | For SIEM / KMS / Data Protection | Base64-encoded 32-byte AES-256-GCM key. Required for the local KMS provider, SIEM connector credential encryption, and encrypted data-protection mode. |
Generating a key:
python3 -c "import os, base64; print(base64.b64encode(os.urandom(32)).decode())"
Deployment mode
| Variable | Default | Scope | Description |
|---|---|---|---|
BEHAVRY_DEPLOYMENT_MODE | standalone | All | standalone, control-plane, or data-plane. |
BEHAVRY_CONTROL_PLANE_URL | https://control.behavry.ai | data-plane | Base URL of the control plane this data plane registers with. |
BEHAVRY_DATA_PLANE_TOKEN | (empty) | data-plane | Token issued by the control plane on registration. |
BEHAVRY_LICENSE_KEY | (empty) | data-plane | License key from tenant_configs.license_key. |
BEHAVRY_DEPLOYMENT_ID | (empty) | data-plane | Stable UUID generated on first startup. |
BEHAVRY_HEARTBEAT_INTERVAL | 60 | data-plane | Seconds between heartbeat posts to the control plane. |
BEHAVRY_CONTROL_PLANE_SIGNING_KEY | (auto-generated in dev) | control-plane | HMAC-SHA256 key signing license-issuance audit records. |
Stripe billing (control-plane only)
| Variable | Default | Description |
|---|---|---|
BEHAVRY_STRIPE_SECRET_KEY | (empty) | Stripe secret key (from Secrets Manager in prod). |
BEHAVRY_STRIPE_WEBHOOK_SECRET | (empty) | Stripe webhook signing secret. |
BEHAVRY_STRIPE_PUBLISHABLE_KEY | (empty) | Stripe publishable key (frontend, informational). |
Feature flags & toggles
| Variable | Default | Description |
|---|---|---|
BEHAVRY_FEATURE_FLAGS | (empty) | Plane-wide flag defaults, e.g. v2_overview=true,v2_agents=false. Per-tenant overrides take precedence. |
BEHAVRY_TENANT_HIERARCHY_ENABLED | false | Channel-partner tenant hierarchy (Sprint CP-CHAN). Enable on the control plane. |
BEHAVRY_MCP_DISCOVERY_ENABLED | true | When an agent calls an unregistered MCP server, audit + escalate + block (shadow-server discovery) instead of a bare error. |
BEHAVRY_APR_ENABLED | true | Assemble Agent Provenance Records from the audit stream (data-plane only). |
BEHAVRY_APR_CLOSE_AFTER_MINUTES | 35 | Minutes of session inactivity before the sweep seals an open APR. |
BEHAVRY_HOME_FORCE_MOSAIC | false | Force the home mosaic even below seeding thresholds (demo/lab first-run). |
BEHAVRY_DASHBOARD_POSTURE | (unset) | single, saas, or channel dashboard chrome. Unset = super-admins default to channel, others to single. |
BEHAVRY_SUPERADMIN_DEFAULT_DATA_PLANE_URL | https://lab.behavry.ai | Data-plane URL returned to super-admin sessions (which have no tenant). |
Observability
| Variable | Default | Description |
|---|---|---|
BEHAVRY_SENTRY_DSN | (empty) | Sentry DSN. Empty disables Sentry (zero overhead). |
BEHAVRY_RELEASE_VERSION | (empty) | Git SHA for Sentry release tracking (set BUILD_SHA in Docker build args). |
BEHAVRY_METRICS_TOKEN | (empty) | Bearer token for the /metrics endpoint. Empty = no auth (dev default). |
BEHAVRY_SSE_KEEPALIVE_SECONDS | 15 | SSE keep-alive interval. Prevents proxy timeouts on the live stream. |
Demo / lab posture
These are only meaningful on demo/lab images (build_posture is image-baked and frozen at startup — never runtime-flippable, it's a security boundary).
| Variable | Default | Description |
|---|---|---|
BEHAVRY_BUILD_POSTURE | production | lab, alpha, demo, or production. Lab/demo images carry the demo-ops surface; production images do not. |
BEHAVRY_ENVIRONMENT | (empty) | Runtime label (lab / alpha / demo) driving the top-bar pill. Unset in production. |
BEHAVRY_DEMO_ENGINE_URL | http://demo-engine:9090 | Demo-engine trigger API (lab posture only). |
BEHAVRY_BOOTSTRAP_MCP_SERVERS | (empty) | JSON array of MCP backends registered into the proxy on every boot. Empty = no-op (production registers nothing). |
Demo external credentials
These are read directly by demo scripts (not core Settings), so they are not BEHAVRY_-prefixed: GITHUB_TOKEN, SLACK_BOT_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY.
Example .env files
Minimal local dev:
BEHAVRY_ENV=development
BEHAVRY_ADMIN_PASSWORD=admin
BEHAVRY_DB_URL=postgresql+asyncpg://behavry:behavry@localhost:5432/behavry
BEHAVRY_OPA_URL=http://localhost:8181
Production (standalone):
BEHAVRY_ENV=production
BEHAVRY_ADMIN_USERNAME=admin
BEHAVRY_ADMIN_PASSWORD=<strong-password>
# Database
BEHAVRY_DB_URL=postgresql+asyncpg://behavry:<db-password>@db:5432/behavry
# OPA
BEHAVRY_OPA_URL=http://opa:8181
BEHAVRY_OPA_FAIL_CLOSED=true
# JWT (paste PEM including header/footer lines)
BEHAVRY_JWT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."
# Audit event signing (Ed25519 base64 seed)
BEHAVRY_AUDIT_SIGNER_PRIVATE_KEY=<base64-32-byte-seed>
# Auth (password | clerk | oidc)
BEHAVRY_AUTH_PROVIDER=password
# URLs / CORS
BEHAVRY_PUBLIC_URL=https://api.your-domain.com
BEHAVRY_CORS_ORIGINS=https://app.your-domain.com
# Data protection / SIEM encryption (if used)
# BEHAVRY_LOCAL_ENCRYPTION_KEY=<base64-32-byte-key>
# Webhooks (optional)
# BEHAVRY_WEBHOOK_URL=https://hooks.slack.com/services/...
# BEHAVRY_WEBHOOK_SECRET=<signing-secret>
Data plane:
BEHAVRY_ENV=production
BEHAVRY_DEPLOYMENT_MODE=data-plane
BEHAVRY_CONTROL_PLANE_URL=https://control.behavry.ai
BEHAVRY_DATA_PLANE_TOKEN=<token-from-control-plane>
BEHAVRY_LICENSE_KEY=<license-key>
BEHAVRY_HEARTBEAT_INTERVAL=60
# Local database
BEHAVRY_DB_URL=postgresql+asyncpg://behavry:<db-password>@db:5432/behavry
# OPA (bundle-polling mode)
BEHAVRY_OPA_URL=http://opa:8181
# Shared admin-token key (from the control plane) so super-admin JWTs verify here
BEHAVRY_JWT_ADMIN_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."
BEHAVRY_JWT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."