Skip to content

Self-host Provon On Cloudflare

Deploy Provon into your own Cloudflare account with independently scalable Workbench, API, Gateway, MCP, OTLP, telemetry pipeline, diagnostics, and maintenance deployments. This path replaces the Node process and local files with Cloudflare platform primitives; it is not a front end for a hosted management service.

View as Markdown Open the plain-text version of this page.

When To Choose This Runtime#

Decision Cloudflare runtime
Workbench availability must not sit on the model-request path Separate Pages and Workers
Ingest, summaries, and diagnostics must scale independently Managed Queues with dedicated consumers
Metadata and usage events need a managed SQL database Shared D1 databases
Telemetry should use object storage with SQL reads R2 Data Catalog / Iceberg with R2 SQL
You operate Cloudflare resources and a CI deployment pipeline Wrangler configs, release commands, and secret bindings

Deployments And Backing Resources#

Deployment Entrypoint or config Responsibility
Workbench Pages services/cloudflare/workbench SvelteKit UI on Pages
API Worker wrangler.api.toml Identity, sessions, control API, telemetry reads
Gateway Worker wrangler.gateway.toml Model traffic, routing, policy, guardrails, usage state
MCP Worker wrangler.mcp.toml Streamable-HTTP MCP ingress and hosted tool state
OTLP Worker wrangler.otel.toml OTLP authentication, validation, staging, queueing
Telemetry Pipeline Worker wrangler.telemetry-pipeline.toml Ingest, gateway-telemetry, and summary queue consumers
Diagnostics Worker wrangler.diagnostics.toml Queued diagnosis execution and coordinator state
Maintenance Worker wrangler.maintenance.toml Cron housekeeping: retention, metadata maintenance, work-item sync
Telemetry Warehouse Worker wrangler.telemetry-warehouse.toml Internal deterministic shard routing for telemetry writes
Warehouse Container Dockerfile.telemetry-warehouse Iceberg append, summary replacement, and retention

The checked-in templates use provon-demo-* resource names for the public demo profile. Keep those names isolated from any other Cloudflare account or deployment; never reuse production resource IDs in demo configs.

Requirements#

  • A Cloudflare account with the platform products used by the checked-in Wrangler configs, including Containers, R2 Data Catalog, and R2 SQL.
  • Node.js 22 or newer, pnpm 10, and Wrangler 4 authenticated for the target account.
  • Custom domains or routes for the Workbench, API, Gateway, MCP, and OTLP origins.
  • API tokens for deployment, R2 SQL reads, and Data Catalog mutations.
  • A secret manager or CI secret store for Worker secrets.

Check the CLI and account before provisioning:

bash
pnpm exec wrangler --version
pnpm exec wrangler whoami

Cloudflare product availability and limits change independently; confirm Containers, Data Catalog, and R2 SQL are enabled for the target account before committing to this topology.

Deployment Flow#

Plan configs Provision resources Wire bindings Set Worker secrets Validate and configure maintenance Build, check, publish Verify request paths

1. Prepare Wrangler Configs#

The .example.toml files declare the complete binding topology:

text
services/cloudflare/wrangler.api.example.toml
services/cloudflare/wrangler.gateway.example.toml
services/cloudflare/wrangler.mcp.example.toml
services/cloudflare/wrangler.otel.example.toml
services/cloudflare/wrangler.telemetry-pipeline.example.toml
services/cloudflare/wrangler.diagnostics.example.toml
services/cloudflare/wrangler.maintenance.example.toml
services/cloudflare/wrangler.telemetry-warehouse.example.toml

Render deployment configs from the repository templates:

bash
pnpm release:plan

Keep neutral binding keys unchanged; fill real IDs and origins in the ignored resources.local.json. Only templates and the non-secret Workbench build default are versioned; actual resource coordinates stay local.

The pipeline reads PROVON_TELEMETRY_QUEUE_NAMES, a JSON mapping with the ingest, gateway-telemetry, and telemetry-summary roles. The release render derives it from the pipeline's queue references; resources.local.json cannot override the mapping, and missing, duplicate, or unknown queue names fail closed. When using a Wrangler template directly, keep the mapping equal to the queue names declared in queues.consumers.

2. Provision Storage And Queues#

pnpm release:resources prints the exact provisioning commands for the active profile and applies only explicitly selected missing resources with --apply --names. The manual equivalents are:

bash
pnpm exec wrangler d1 create provon-demo-meta
pnpm exec wrangler d1 create provon-demo-metering
pnpm exec wrangler kv namespace create provon-demo-gateway-cache

pnpm exec wrangler r2 bucket create provon-demo-blobs
pnpm exec wrangler r2 bucket create provon-demo-telemetry
pnpm exec wrangler r2 bucket catalog enable provon-demo-telemetry

pnpm exec wrangler queues create provon-demo-ingest
pnpm exec wrangler queues create provon-demo-ingest-dlq
pnpm exec wrangler queues create provon-demo-telemetry-summary
pnpm exec wrangler queues create provon-demo-gateway-telemetry
pnpm exec wrangler queues create provon-demo-diagnostics

pnpm exec wrangler pages project create provon-demo-app --production-branch main

Record both D1 database IDs, the KV namespace ID, the Data Catalog URI and warehouse name, and the account ID. Multiple Workers bind the same metadata D1 (API, Gateway, MCP, OTLP, pipeline, diagnostics, and maintenance); the usage-events D1 is shared by the API, pipeline, diagnostics, and maintenance deployments. Do not create per-worker copies of either database.

3. Bindings Matrix#

Binding kind API Gateway MCP OTLP Pipeline Diagnostics Maintenance Warehouse
Meta D1 (PROVON_META_DB) yes yes yes yes yes yes yes —
Usage-events D1 (PROVON_METERING_DB) yes — — — yes yes yes —
Blob R2 (PROVON_BLOB_BUCKET) yes yes — yes yes yes yes —
Gateway cache KV — yes — — — — — —
Queue producers / consumers — gateway-telemetry producer — ingest, summary producers all three consumers; ingest DLQ producer diagnostics producer and consumer — —
Service bindings Warehouse executor, Gateway runtime, MCP runtime — Warehouse executor Warehouse executor Warehouse executor Warehouse executor, Gateway runtime Warehouse executor —
Durable Objects Coordinator (remote) Usage state, target state Runtime state — Coordinator (remote) Coordinator (local) — Executor container

Worker-specific wiring notes:

  • API: bind both D1 databases and the blob bucket; set R2 SQL coordinates; bind the warehouse executor, Gateway runtime (GatewayRuntimeEntrypoint), and MCP runtime (McpRuntimeEntrypoint); set Workbench origins and cookie policy.
  • Gateway: bind the meta D1, cache KV, blob bucket, and the gateway-telemetry producer; preserve the GatewayUsageStateDurableObject and GatewayTargetStateDurableObject classes and their migrations. The API and diagnostics Workers reach the Gateway over the PROVON_GATEWAY_RUNTIME service binding; the Gateway needs no extra inbound route beyond its public origin.
  • MCP: bind the meta D1 and preserve McpRuntimeStateDurableObject; the API reaches the MCP Worker over PROVON_MCP.
  • OTLP: bind the meta D1 and blob bucket; bind the ingest and summary producers and the warehouse service; use the same R2 SQL coordinates as the readers.
  • Pipeline: bind both D1 databases, the blob bucket, the three queue consumers and the ingest DLQ producer, and the warehouse service; it does not call models.
  • Diagnostics: bind both D1 databases, the diagnostics queue, the local coordinator Durable Object, the Gateway runtime service, and the warehouse service.
  • Maintenance: bind both D1 databases and the blob bucket; preserve the cron trigger (0 */6 * * *).
  • Warehouse: set PROVON_R2_CATALOG_URI, PROVON_R2_CATALOG_WAREHOUSE, R2 object coordinates, and the catalog token; preserve the Container and executor Durable Object bindings; workers_dev stays disabled.

4. Configure Public Origins#

A typical split-domain layout:

Deployment Example
Workbench https://app.provon.example
API https://api.provon.example
Gateway https://gateway.provon.example
MCP https://mcp.provon.example
OTLP https://otel.provon.example

API Worker variables:

toml
[vars]
PROVON_AUTH_ORIGIN = "https://api.provon.example"
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:

text
https://api.provon.example/auth/callback/github
https://api.provon.example/auth/callback/google
https://api.provon.example/v1/integrations/github/callback

Use exact browser origins in PROVON_WORKBENCH_ORIGINS; do not use * for a credentialed Workbench. The Pages build receives the API origin from resources.local.json origins.api.

5. Set Secrets#

Generate one stable PROVON_AUTH_SECRET for this deployment and set it on every runtime that reads sessions or encrypted project credentials. Keep per-worker secret JSON files outside version control, then push them with the release entrypoint:

bash
pnpm release:secrets --only api --file secrets.api.json
pnpm release:secrets --only gateway --file secrets.gateway.json
pnpm release:secrets --only mcp --file secrets.mcp.json
pnpm release:secrets --only otel --file secrets.otel.json
pnpm release:secrets --only telemetry-pipeline --file secrets.telemetry-pipeline.json
pnpm release:secrets --only diagnostics --file secrets.diagnostics.json
pnpm release:secrets --only maintenance --file secrets.maintenance.json
pnpm release:secrets --only telemetry-warehouse --file secrets.telemetry-warehouse.json

Scoping rules:

  • PROVON_R2_SQL_TOKEN goes only to telemetry readers; PROVON_R2_DATA_CATALOG_TOKEN goes only to the warehouse writer.
  • Identity-provider and Connector secrets belong only to their consuming Workers.
  • The demo secret entrypoint rejects payment-provider and official-provider credential material; do not add those values to this deployment.

See Configuration for the full variable contract.

6. Validate And Deploy#

Run the Worker validation chain:

bash
pnpm test:cf

Inspect telemetry maintenance configuration before applying it:

bash
pnpm configure:cf:telemetry-maintenance
pnpm configure:cf:telemetry-maintenance:apply

The dry run lists the R2 lifecycle rules and Data Catalog settings it would configure: OTLP and Gateway staging objects expire after 7 days by default; snapshot expiration keeps at least a 15-day window for queue-replay idempotency and retains the last 10 snapshots; compaction targets 64 MB files (allowed sizes 64, 128, 256, 512 MB). Applying requires PROVON_R2_SQL_TOKEN or CLOUDFLARE_API_TOKEN.

Build, check, and publish the fixed artifacts:

bash
pnpm release:build
pnpm release:check
pnpm release:publish

Publishing uploads fixed artifacts only; it does not create resources or initialize D1. Prepare the current baseline schema explicitly before the first application release:

bash
pnpm release:db-init --remote

The project keeps only the current initialization baseline; development refactors do not preserve old schema compatibility or migrate historical data. See the release workflow reference in scripts/release/README.md.

7. Verify Public Request Endpoints#

bash
curl --fail --silent https://api.provon.example/healthz
curl --fail --silent https://gateway.provon.example/healthz
curl --fail --silent https://mcp.provon.example/healthz
curl --fail --silent https://otel.provon.example/healthz

Request-facing Workers return JSON health; the pipeline, diagnostics, and maintenance Workers return plain healthz: ok, and the warehouse Worker responds on /health.

End-to-end checks:

  1. Open the Workbench and sign in.
  2. Create a project API key through the API.
  3. Send OTLP to the OTLP origin and wait for the trace to become queryable through the API.
  4. Send a model request to the Gateway origin and confirm its provider-attempt trace.
  5. Confirm scheduled retention and maintenance task logs.

Note

A 2xx OTLP response means the payload was accepted and queued. It does not prove the pipeline Worker, warehouse Container, Data Catalog, or R2 SQL read path completed.

Local Cloudflare Development#

Create .dev.vars from .dev.vars.example (PROVON_AUTH_SECRET and, when querying real telemetry, PROVON_R2_SQL_TOKEN), then start the Workers:

bash
pnpm dev:cf

This starts the API Worker as the primary Wrangler process with the OTLP, Gateway, MCP, pipeline, diagnostics, and maintenance Workers as auxiliary services. Start the Workbench separately:

bash
pnpm dev:pages

Use per-Worker dev:worker:* scripts when isolating one Worker. Local emulation does not replace a staging environment that exercises real Queues, R2 SQL, Data Catalog, Containers, and Service Bindings.

Current Constraints#

  • Telemetry reads require the Cloudflare R2 SQL backend.
  • The default read model uses trace summaries and requires the summary queue on writer deployments.
  • The warehouse Container and its Service Binding are required for Iceberg mutations.
  • Cloudflare resource cost, service limits, regions, and recovery guarantees remain account-level operator responsibilities.