Self-hosting Configuration
Configure Provon through environment variables and runtime bindings. Keep deployment coordinates in version control, keep secret values in a secret manager, and use the same semant
Critical Secret#
AUTH_SECRET is required in production. PROVON_AUTH_SECRET is an equivalent fallback, but use one
name consistently.
This value:
- signs authentication state and sessions;
- derives application-level encryption for stored OAuth tokens, provider credentials, and Connector secrets;
- must be identical across runtime surfaces that read the same metadata store.
Generate at least 32 random bytes:
openssl rand -base64 32Store and back it up as encryption key material. Replacing it invalidates sessions and can make existing encrypted credentials unreadable. Do not rotate it without an explicit credential re-encryption and user reauthorization plan.
Public Origin And HTTP#
| Variable | Runtime | Purpose |
|---|---|---|
PROVON_HTTP_HOST |
Node | Bind address; defaults to 127.0.0.1 |
PROVON_HTTP_PORT |
Node | Listen port; defaults to 3000 |
PROVON_SERVE_WORKBENCH |
Node | Set to 0 only for an intentional API-only host |
PROVON_AUTH_ORIGIN |
Both | Exact public origin used for OAuth callbacks |
PROVON_WORKBENCH_ORIGINS |
Both | Comma-separated exact browser origins allowed to use the API |
PROVON_AUTH_COOKIE_DOMAIN |
Both | Shared parent cookie domain for split subdomains |
PROVON_AUTH_TRUST_HOST |
Both | Trust forwarded public host when set to true behind a proxy |
PROVON_VERSION |
Both | Version reported by /healthz |
For a same-origin Node deployment:
PROVON_AUTH_ORIGIN=https://provon.example.com
PROVON_WORKBENCH_ORIGINS=https://provon.example.com
PROVON_AUTH_TRUST_HOST=trueFor split Cloudflare origins:
PROVON_AUTH_ORIGIN=https://api.provon.example
PROVON_WORKBENCH_ORIGINS=https://app.provon.example
PROVON_AUTH_COOKIE_DOMAIN=.provon.example
PROVON_AUTH_TRUST_HOST=trueOnly trust forwarded hosts when the ingress removes client-supplied forwarding headers and writes
its own values. Forwarded origins that do not exactly match PROVON_AUTH_ORIGIN are ignored.
Node Storage#
| Variable | Default | Purpose |
|---|---|---|
PROVON_META_DB_URL |
libsql:.provon/data/meta.db |
Metadata database URL |
PROVON_META_DB_AUTH_TOKEN |
None | Remote metadata libSQL authentication |
PROVON_METERING_DB_URL |
libsql:.provon/data/metering.db |
Billable usage event database URL |
PROVON_METERING_DB_AUTH_TOKEN |
None | Remote metering libSQL authentication |
PROVON_TELEMETRY_DB_URL |
duckdb:.provon/data/telemetry.duckdb |
duckdb:<path> or motherduck:<database> |
PROVON_BLOBS_DIR |
.provon/blobs |
Blobs, staged payloads, and runtime data root |
PROVON_MODELS_DIR |
Sibling models directory |
Model weights and artifacts |
Metadata, metering, and telemetry must use distinct database URLs.
The directory containing PROVON_BLOBS_DIR also holds persistent Node runtime state. Mount or
back up the parent data directory, not only the visible blob files.
Model Services#
The Node runtime can optionally control standalone Python services for local inference and fine-tuning. These services run outside the Node process and communicate over HTTP.
| Variable | Default | Purpose |
|---|---|---|
PROVON_PYTHON_INFERENCE_URL |
none | Base URL of services/python-inference |
PROVON_PYTHON_INFERENCE_API_KEY |
none | Shared bearer token for inference service |
PROVON_PYTHON_FINE_TUNING_URL |
http://127.0.0.1:8001 |
Base URL of services/python-fine-tuning |
PROVON_PYTHON_FINE_TUNING_API_KEY |
none | Shared bearer token for fine-tuning service |
When the inference URL is unset, the runtime still operates but cannot serve self/ targets. When
the fine-tuning URL is unset, fine-tuning API routes return 503.
The Python services themselves accept:
PROVON_HOST/PROVON_PORTfor binding;PROVON_API_KEYfor authentication;PROVON_MODELS_DIRfor the inference model cache;PROVON_LLAMA_CPP_PATHfor GGUF export in the fine-tuning service.
MotherDuck#
| Variable | Purpose |
|---|---|
MOTHERDUCK_TOKEN |
Shared telemetry database access |
MOTHERDUCK_ADMIN_TOKEN |
Organization-isolated database and service-account setup |
MOTHERDUCK_HOST |
Postgres endpoint override |
MOTHERDUCK_PORT |
Postgres endpoint port |
MOTHERDUCK_USER |
Postgres endpoint user |
MOTHERDUCK_SESSION_HINT |
Optional session routing hint |
PROVON_TELEMETRY_TENANT_ISOLATION |
organization or shared; defaults to organization |
MOTHERDUCK_SERVICE_ACCOUNT_TOKEN_TTL_SECONDS |
Generated organization token lifetime |
MOTHERDUCK_DUCKLING_SIZE |
Optional organization compute size |
MOTHERDUCK_READ_SCALING_POOL_SIZE |
Optional read scaling pool size |
Use:
PROVON_TELEMETRY_DB_URL=motherduck:provon-telemetry
PROVON_TELEMETRY_TENANT_ISOLATION=shared
MOTHERDUCK_TOKEN=...for one shared MotherDuck database. Use the default organization isolation with
MOTHERDUCK_ADMIN_TOKEN when each organization should receive isolated MotherDuck resources.
Cloudflare Telemetry#
The Cloudflare runtime requires:
| Variable or binding | Purpose |
|---|---|
PROVON_TELEMETRY_BACKEND |
Must be cloudflare-r2-sql |
PROVON_R2_SQL_ACCOUNT_ID |
Cloudflare account containing telemetry |
PROVON_R2_SQL_BUCKET |
Data Catalog-enabled telemetry bucket |
PROVON_R2_SQL_NAMESPACE |
Base R2 SQL namespace |
PROVON_R2_SQL_TOKEN |
R2 SQL API token secret |
PROVON_R2_CATALOG_URI |
Iceberg REST catalog URI for the warehouse runtime |
PROVON_R2_CATALOG_WAREHOUSE |
Data Catalog warehouse name |
PROVON_R2_DATA_CATALOG_TOKEN |
Read-write catalog token for telemetry mutations |
PROVON_TELEMETRY_WAREHOUSE_CACHE_MAX_TABLES |
Maximum per-container table runtimes retained in memory; defaults to 256 |
PROVON_BLOB_BUCKET |
R2 binding for staging and blobs |
PROVON_TELEMETRY_WAREHOUSE_EXECUTOR |
Internal Service Binding for telemetry mutations |
The default read model is:
PROVON_TELEMETRY_QUERY_SOURCE = "summaries"
PROVON_TELEMETRY_PAYLOAD_RETENTION = "all"summaries requires the TELEMETRY_SUMMARY_QUEUE binding on telemetry writer runtimes.
projected-only drops raw payload fields at the Cloudflare telemetry write boundary. Choose it only
when projected evidence is sufficient for investigation and diagnosis.
Use the checked-in wrangler.*.example.toml files as the binding contract. Do not rename a binding
without changing the corresponding runtime code.
OTLP And Background Work#
Defaults are suitable for development and moderate workloads. Tune only from measured body sizes, queue lag, write latency, and dependency limits.
| Variable | Default | Purpose |
|---|---|---|
PROVON_OTLP_MAX_BYTES |
10485760 |
Decoded HTTP payload ceiling |
PROVON_OTLP_MAX_BATCH_BYTES |
16777216 |
Soft bytes claimed per ingest tick |
PROVON_OTLP_MAX_JOB_BYTES |
16777216 |
Hard ceiling for one staged job |
PROVON_OTLP_WORKER_INTERVAL_MS |
250 |
Node ingest worker interval; 0 disables it |
PROVON_OTLP_WORKER_BATCH_SIZE |
50 |
Jobs claimed per Node tick |
PROVON_OTLP_WORKER_LOCK_MS |
60000 |
Ingest claim lease |
PROVON_OTLP_FLUSH_MAX_ROWS |
2000 |
Soft rows per write group |
PROVON_OTLP_FLUSH_MAX_BYTES |
8388608 |
Soft bytes per write group |
PROVON_OTLP_MAX_PENDING_JOBS |
10000 |
Admission ceiling for queued ingest |
PROVON_OTLP_CLEANUP_INTERVAL_MS |
3600000 |
Completed-job cleanup interval |
PROVON_OTLP_CLEANUP_OLDER_THAN_MS |
86400000 |
Completed-job age before cleanup |
Node also exposes:
| Variable | Default | Purpose |
|---|---|---|
PROVON_TELEMETRY_SUMMARY_MATERIALIZATION_INTERVAL_MS |
5000 |
Summary queue drain interval |
PROVON_DIAGNOSTIC_RULE_INTERVAL_MS |
60000 |
Ready diagnostic Run polling interval |
PROVON_DIAGNOSTIC_RULE_BATCH_SIZE |
100 |
Diagnostic Runs claimed per tick |
PROVON_REPAIR_STATUS_SYNC_INTERVAL_MS |
300000 |
GitHub repair-status polling interval |
Gateway reservation cleanup exposes additional controls:
| Variable | Runtime | Default | Purpose |
|---|---|---|---|
PROVON_GATEWAY_PTB_RECONCILIATION_ENABLED |
Node, Cloudflare | Enabled | Disable stale managed-credit reconciliation |
PROVON_GATEWAY_PTB_RECONCILIATION_INTERVAL_MS |
Node | 60000 |
Managed-credit cleanup loop interval |
PROVON_GATEWAY_PTB_STALE_RESERVATION_MS |
Node | 600000 |
Managed-credit reservation age threshold |
PROVON_GATEWAY_PTB_STALE_RESERVATION_MS |
Cloudflare Jobs | 1800000 |
Managed-credit reservation age threshold |
PROVON_GATEWAY_PTB_RECONCILIATION_BATCH_SIZE |
Node, Cloudflare | 100 |
Managed-credit reservations released/tick |
PROVON_GATEWAY_USAGE_RECONCILIATION_ENABLED |
Node | Enabled | Disable stale usage-policy reconciliation |
PROVON_GATEWAY_USAGE_RECONCILIATION_INTERVAL_MS |
Node | 60000 |
Usage-policy cleanup loop interval |
PROVON_GATEWAY_USAGE_STALE_RESERVATION_MS |
Node | 600000 |
Usage-policy reservation age threshold |
PROVON_GATEWAY_USAGE_RECONCILIATION_BATCH_SIZE |
Node | 100 |
Usage-policy reservations released/tick |
Setting an interval to 0 disables the corresponding loop only where the implementation accepts a
non-negative interval. Disabling a loop is an architecture change: assign its responsibility to
another runtime before doing so.
Data Retention#
Project retention policy selects what should expire. Runtime variables control the maintenance job:
| Variable | Default | Purpose |
|---|---|---|
PROVON_DATA_RETENTION_INTERVAL_MS |
21600000 |
Node retention interval |
PROVON_DATA_RETENTION_BATCH_SIZE |
10 |
Projects or organizations per run |
PROVON_DATA_RETENTION_DELETE_TIMEOUT_MS |
60000 |
Delete timeout |
PROVON_DATA_RETENTION_MAX_RETRIES |
3 |
Retry count |
PROVON_DATA_RETENTION_DELETE_MAX_FILES |
128 |
Iceberg files deleted per bounded operation |
Cloudflare scheduled retention runs through the Jobs Worker and telemetry warehouse. R2 lifecycle, snapshot expiration, and compaction are separate platform maintenance controls.
Sign-in Providers#
Email and password remain available when no social provider is configured. A social provider is enabled only when both its client ID and client secret are present.
| Provider | Required variables | Optional |
|---|---|---|
| GitHub | AUTH_GITHUB_CLIENT_ID, AUTH_GITHUB_CLIENT_SECRET |
None |
AUTH_GOOGLE_CLIENT_ID, AUTH_GOOGLE_CLIENT_SECRET |
None | |
| Apple | AUTH_APPLE_CLIENT_ID, AUTH_APPLE_CLIENT_SECRET |
AUTH_APPLE_ALLOW_ACCOUNT_LINKING |
Register:
https://<api-origin>/api/auth/callback/github
https://<api-origin>/api/auth/callback/google
https://<api-origin>/api/auth/callback/appleGoogle and GitHub identities require verified provider email claims. To link another identity, sign in first and use Account settings → Sign-in methods. Anonymous email-based account linking is not supported.
Enterprise OIDC#
Required:
AUTH_OIDC_CLIENT_IDAUTH_OIDC_CLIENT_SECRETAUTH_OIDC_ISSUERorAUTH_OIDC_WELL_KNOWN
Optional controls include AUTH_OIDC_NAME, AUTH_OIDC_SCOPE,
AUTH_OIDC_TOKEN_ENDPOINT_AUTH_METHOD, AUTH_OIDC_ALLOW_ACCOUNT_LINKING, and
AUTH_OIDC_EMAIL_TRUST_POLICY.
The default email trust policy requires email_verified=true. Use trusted_provider only when the
IdP contract guarantees email ownership. The callback provider ID is enterprise-oidc:
https://<api-origin>/api/auth/callback/enterprise-oidcConnector OAuth#
Login OAuth and Connector OAuth are separate applications. Connector credentials use the
*_INTEGRATION_* prefix.
| Connector | Required variables | Optional scope override |
|---|---|---|
| GitHub | GITHUB_INTEGRATION_CLIENT_ID, GITHUB_INTEGRATION_CLIENT_SECRET |
GITHUB_INTEGRATION_SCOPES |
| Slack | SLACK_INTEGRATION_CLIENT_ID, SLACK_INTEGRATION_CLIENT_SECRET |
SLACK_INTEGRATION_SCOPES |
| Notion | NOTION_INTEGRATION_CLIENT_ID, NOTION_INTEGRATION_CLIENT_SECRET |
None |
| Jira | JIRA_INTEGRATION_CLIENT_ID, JIRA_INTEGRATION_CLIENT_SECRET |
JIRA_INTEGRATION_SCOPES |
| Linear | LINEAR_INTEGRATION_CLIENT_ID, LINEAR_INTEGRATION_CLIENT_SECRET |
LINEAR_INTEGRATION_SCOPES |
Register:
https://<api-origin>/v1/integrations/github/callback
https://<api-origin>/v1/integrations/slack/callback
https://<api-origin>/v1/integrations/notion/callback
https://<api-origin>/v1/integrations/jira/callback
https://<api-origin>/v1/integrations/linear/callbackSee Connectors for project setup and default scopes.
Model Runtime#
The model runtime stores local model weights under PROVON_MODELS_DIR and keeps its
process state in a fixed file at <data-dir>/data/model-runtime.json. The data directory is resolved
from the parent of PROVON_BLOBS_DIR, or from XDG_DATA_HOME when no blob directory is configured.
Node controls standalone Python inference and fine-tuning services over HTTP:
PROVON_PYTHON_INFERENCE_URLPROVON_PYTHON_INFERENCE_API_KEYPROVON_PYTHON_FINE_TUNING_URLPROVON_PYTHON_FINE_TUNING_API_KEYPROVON_MODEL_FINE_TUNING_WORK_DIRPROVON_TRANSFORMERS_DEVICEPROVON_TRANSFORMERS_DTYPEPROVON_TRANSFORMERS_TRUST_REMOTE_CODE=1
Node stages immutable training data under PROVON_MODEL_FINE_TUNING_WORK_DIR. The fine-tuning
service writes its checkpoint under the same job directory, then Node atomically imports the
standalone model into PROVON_MODELS_DIR. When the services run in separate containers,
mount the training work directory at the same absolute path in both containers. See
Model providers.
Configuration Review#
Before production:
- compare staging and production variable names without comparing secret values;
- confirm every runtime reading one metadata store has the same
AUTH_SECRET; - verify exact Workbench origins and public callback URLs;
- verify storage paths or bindings point to durable production resources;
- keep body, queue, and retention limits consistent across producer and consumer surfaces;
- restart or redeploy all affected surfaces after a shared secret or binding change;
- record the configuration version with the application release.