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 |
Local DuckDB telemetry database path |
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.
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. Runtime process state
(active downloads, running services, engine installs, and the catalog cache) is kept in memory
only and is reset when the Node process restarts. Installed models are rediscovered from
<model-dir>/manifest.json files, and partial downloads can resume from .part files.
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.