Self-host Provon On Cloudflare
The Cloudflare runtime deploys Provon into your Cloudflare account with independently scalable Workbench, API, Gateway, OTLP, jobs, and telemetry warehouse surfaces.
On this page Browse sections
This is the advanced self-hosting path. It replaces the Node process and local stores with Cloudflare platform primitives; it is not a remote front end for a Provon-hosted control plane.
Architecture#
| Surface | Entrypoint or config | Responsibility |
|---|---|---|
| Workbench | services/cloudflare-worker/workbench |
SvelteKit UI on Pages |
| API Worker | wrangler.api.toml |
Identity, sessions, control API, and telemetry reads |
| Gateway Worker | wrangler.gateway.toml |
Model traffic, routing, policy, and trace capture |
| OTLP Worker | wrangler.otel.toml |
OTLP authentication, validation, staging, and queue |
| Jobs Worker | wrangler.jobs.toml |
Queue consumers, diagnostics, summaries, and cron |
| Telemetry warehouse Worker | wrangler.telemetry-warehouse.toml |
Internal organization routing for telemetry writes |
| Warehouse Container | Dockerfile.telemetry-warehouse |
Iceberg append, summary replacement, and retention |
Backing services are D1, R2, R2 Data Catalog, R2 SQL, KV, Queues, Durable Objects, Containers, and Pages. See Self-hosting architecture for the complete data flow.
Requirements#
- A Cloudflare account with the platform products used by the checked-in Wrangler configs.
- Node.js 22 or newer and pnpm 10.
- Wrangler 4 authentication for the target account.
- Custom domains or routes for the Workbench, API, Gateway, and OTLP surfaces.
- API tokens for deployment, R2 SQL reads, and R2 Data Catalog mutations.
- A secret manager or CI secret store.
Check the installed CLI and account before provisioning:
pnpm exec wrangler --version
pnpm exec wrangler whoamiCloudflare product availability and limits change independently. Confirm that Containers, R2 Data Catalog, and R2 SQL are enabled for the target account before committing to this architecture.
1. Prepare Wrangler Configs#
The .example.toml files declare the complete binding topology:
services/cloudflare-worker/wrangler.api.example.toml
services/cloudflare-worker/wrangler.gateway.example.toml
services/cloudflare-worker/wrangler.otel.example.toml
services/cloudflare-worker/wrangler.jobs.example.toml
services/cloudflare-worker/wrangler.telemetry-warehouse.example.tomlCreate environment-specific configs from them. Keep binding names unchanged; replace resource IDs, account coordinates, domains, and service names for the target environment.
The tracked wrangler.*.toml files are deployment inputs. Do not put secret values in them.
2. Provision Storage And Queues#
Create the named resources:
pnpm exec wrangler d1 create provon-meta
pnpm exec wrangler kv namespace create provon-gateway-cache
pnpm exec wrangler r2 bucket create provon-blobs
pnpm exec wrangler r2 bucket create provon-telemetry
pnpm exec wrangler r2 bucket catalog enable provon-telemetry
pnpm exec wrangler queues create provon-ingest
pnpm exec wrangler queues create provon-ingest-dlq
pnpm exec wrangler queues create provon-telemetry-summary
pnpm exec wrangler queues create provon-workflow-runs
pnpm exec wrangler pages project create provon-app --production-branch mainRecord:
- the D1 database ID;
- the KV namespace ID;
- the R2 Data Catalog URI and warehouse name;
- the Cloudflare account ID.
Do not create separate metadata databases or telemetry buckets for each Worker. The surfaces share one deployment boundary through bindings.
3. Wire The Bindings#
Update the environment-specific configs:
API#
- bind
PROVON_META_DBtoprovon-meta; - bind
PROVON_BLOB_BUCKETtoprovon-blobs; - set the R2 SQL account, bucket, and namespace;
- bind the telemetry warehouse and Jobs Worker services;
- set Workbench origins and cookie policy.
Gateway#
- bind the same D1 database;
- bind
PROVON_GATEWAY_CACHEto the KV namespace; - bind Gateway telemetry and workflow producers;
- preserve the checked-in Durable Object classes and migrations.
OTLP#
- bind the same D1 database and blob bucket;
- bind the ingest and telemetry-summary producers;
- bind the telemetry warehouse service;
- use the same R2 SQL coordinates as the API and Jobs Worker.
Jobs#
- bind the same D1 database and blob bucket;
- bind and consume the ingest, telemetry-summary, and workflow queues;
- bind the ingest DLQ;
- bind the Gateway model and telemetry warehouse services;
- preserve the scheduled triggers.
Telemetry Warehouse#
- set
PROVON_R2_CATALOG_URIandPROVON_R2_CATALOG_WAREHOUSEfrom catalog creation; - set the R2 object endpoint and account coordinates;
- preserve the Container and Durable Object bindings.
Workbench#
Set PROVON_API_ORIGIN to the public API origin in
services/cloudflare-worker/workbench/wrangler.toml.
4. Configure Public Origins#
A typical split-domain layout is:
| Surface | Example |
|---|---|
| Workbench | https://app.provon.example |
| API | https://api.provon.example |
| Gateway | https://gateway.provon.example |
| OTLP | https://otel.provon.example |
Set on the API Worker:
[vars]
PROVON_AUTH_TRUST_HOST = "true"
PROVON_AUTH_COOKIE_DOMAIN = ".provon.example"
PROVON_WORKBENCH_ORIGINS = "https://app.provon.example"Register sign-in and Connector OAuth callbacks on the public API origin:
https://api.provon.example/api/auth/callback/github
https://api.provon.example/api/auth/callback/google
https://api.provon.example/v1/integrations/github/callbackUse exact browser origins in PROVON_WORKBENCH_ORIGINS. Do not use * for a credentialed
Workbench.
5. Set Secrets#
Generate one stable AUTH_SECRET and set the same value on every runtime that reads sessions or
encrypted project credentials:
pnpm exec wrangler secret put AUTH_SECRET --config services/cloudflare-worker/wrangler.api.toml
pnpm exec wrangler secret put AUTH_SECRET --config services/cloudflare-worker/wrangler.gateway.toml
pnpm exec wrangler secret put AUTH_SECRET --config services/cloudflare-worker/wrangler.otel.toml
pnpm exec wrangler secret put AUTH_SECRET --config services/cloudflare-worker/wrangler.jobs.tomlEnter the same secret through each interactive prompt. Do not pass it as a command argument or store it in TOML.
Set the R2 SQL read token on surfaces that query telemetry:
pnpm exec wrangler secret put PROVON_R2_SQL_TOKEN --config services/cloudflare-worker/wrangler.api.toml
pnpm exec wrangler secret put PROVON_R2_SQL_TOKEN --config services/cloudflare-worker/wrangler.otel.toml
pnpm exec wrangler secret put PROVON_R2_SQL_TOKEN --config services/cloudflare-worker/wrangler.jobs.tomlSet the Data Catalog read-write token on the warehouse runtime:
pnpm exec wrangler secret put PROVON_R2_DATA_CATALOG_TOKEN \
--config services/cloudflare-worker/wrangler.telemetry-warehouse.tomlAdd identity-provider, model-provider, billing, and Connector secrets only to the runtimes that use them. See Self-hosting configuration.
6. Validate And Deploy#
Run the Worker validation chain:
pnpm test:cfInspect telemetry maintenance commands before applying them:
pnpm configure:cf:telemetry-maintenance
pnpm configure:cf:telemetry-maintenance:applyThe maintenance configuration adds:
- expiration for staged OTLP payloads;
- Data Catalog snapshot expiration with an idempotency-safe minimum;
- Iceberg compaction.
Deploy the complete stack:
pnpm deploy:cfThe command applies D1 migrations first, then deploys the telemetry warehouse, OTLP, Gateway, Jobs, API, and Workbench surfaces. It stops before publishing new Worker code when the metadata migration fails.
Never rename or rewrite a migration that reached a persistent environment. Add a forward migration for the next schema change.
7. Verify Each Surface#
Verify runtime health:
curl --fail --silent https://api.provon.example/healthz
curl --fail --silent https://gateway.provon.example/healthz
curl --fail --silent https://otel.provon.example/healthzThen run separate end-to-end checks:
- Open the Workbench and sign in.
- Create a project API key through the API surface.
- Send OTLP to the OTel origin and wait for the trace to become queryable through the API.
- Send a model request to the Gateway origin and confirm its provider-attempt trace.
- Run one workflow or diagnostic Rule and confirm the Jobs Worker consumes it.
- Confirm scheduled retention and stale-reservation maintenance logs.
A 2xx OTLP response means the payload was accepted and queued. It does not prove that the Jobs
Worker, warehouse Container, R2 Data Catalog, or R2 SQL read path completed.
Local Cloudflare Development#
Create .dev.vars from .dev.vars.example, then run:
pnpm dev:cfThis starts the API Worker as the primary Wrangler process and includes the OTel, Gateway, and Jobs Workers as auxiliary services. Start the Workbench separately:
pnpm dev:pagesUse surface-specific dev:worker:* scripts when isolating one Worker. Local emulation is not a
substitute for a staging environment that exercises real Queues, R2 SQL, Data Catalog, Containers,
and Service Bindings.
Current Constraints#
- Local
self/*model execution is Node-only. - Telemetry reads require the Cloudflare R2 SQL backend.
- The default read model uses trace summaries and requires the telemetry-summary queue on writer surfaces.
- The warehouse Container and its Service Binding are required for Iceberg mutations.
- Cloudflare resource cost, quotas, regions, and recovery guarantees remain account-level operator responsibilities.