Self-host Provon With Node
The Node runtime is the default self-hosting path. One process serves the Workbench, API, Gateway, OTLP ingest, background loops, and optional local model runtime.
On this page Browse sections
Use it for a VM, bare-metal host, Docker host, private cloud, or a single-instance container platform. Read Self-hosting architecture before adding replicas: the default queues and runtime state are local to one data directory.
Requirements#
- Node.js 22 or newer and pnpm 10 for a source deployment, or Docker for a container deployment.
- A durable filesystem for metadata, local telemetry, blobs, queue state, and model artifacts.
- An HTTPS reverse proxy or platform load balancer for public traffic.
- Outbound access to enabled model providers, identity providers, and connectors.
- A stable production
AUTH_SECRET.
For production, allocate storage from expected trace volume and payload capture policy rather than from metadata size. Prompt bodies, tool results, attachments, and retained raw OTLP payloads usually dominate growth.
Option A: Docker#
Build the checked-in production image:
docker build --target runtime -t provon:local .
docker volume create provon-dataGenerate and store a secret in your secret manager:
openssl rand -base64 32Start one instance with local SQLite, DuckDB, blobs, and runtime state on the durable volume:
export AUTH_SECRET="replace-with-secret-manager-value"
docker run -d \
--name provon \
--restart unless-stopped \
-p 127.0.0.1:3000:3000 \
-v provon-data:/data \
-e NODE_ENV=production \
-e AUTH_SECRET \
-e PROVON_HTTP_HOST=0.0.0.0 \
-e PROVON_HTTP_PORT=3000 \
-e PROVON_META_DB_URL=libsql:/data/meta.db \
-e PROVON_TELEMETRY_DB_URL=duckdb:/data/telemetry.duckdb \
-e PROVON_LOCAL_BLOB_DIR=/data/blobs \
-e PROVON_SELF_HOSTED_DIR=/data/self-hosted \
-e PROVON_AUTH_TRUST_HOST=true \
-e PROVON_WORKBENCH_ORIGINS=https://provon.example.com \
provon:localKeep the host port bound to loopback when a reverse proxy runs on the same host. On a container
platform, expose port 3000 only through the platform ingress.
The image runs as uid and gid 1001. If you replace the named volume with a bind mount, make its
directories writable by that identity before starting the container.
About Docker Compose#
The checked-in docker-compose.yml is a development and integration topology. It:
- builds the same Node image;
- uses MotherDuck for telemetry;
- starts the example TypeScript agent;
- must be adapted to the selected MotherDuck isolation mode and credentials.
Do not treat it as a production manifest without removing the example workload, defining secret
delivery, adding durable backup policy, and configuring the public origin. For shared MotherDuck,
set PROVON_TELEMETRY_TENANT_ISOLATION=shared in the service environment and provide
MOTHERDUCK_TOKEN; organization isolation requires MOTHERDUCK_ADMIN_TOKEN.
Option B: Run From Source#
Install and build:
pnpm install --frozen-lockfile
pnpm --filter @provon/node-server buildSet production configuration:
export NODE_ENV=production
export AUTH_SECRET="replace-with-secret-manager-value"
export PROVON_HTTP_HOST=127.0.0.1
export PROVON_HTTP_PORT=3000
export PROVON_META_DB_URL="libsql:/srv/provon/meta.db"
export PROVON_TELEMETRY_DB_URL="duckdb:/srv/provon/telemetry.duckdb"
export PROVON_LOCAL_BLOB_DIR="/srv/provon/blobs"
export PROVON_SELF_HOSTED_DIR="/srv/provon/self-hosted"
export PROVON_AUTH_TRUST_HOST=true
export PROVON_WORKBENCH_ORIGINS="https://provon.example.com"Start the deployable entrypoint:
pnpm --filter @provon/node-server startUse a process supervisor that:
- restarts the process after failure;
- sends
SIGTERMfor graceful shutdown; - allows enough time for HTTP connections and background loops to stop;
- captures stdout and stderr;
- starts only one active instance for the data directory.
The server applies metadata migrations before it begins listening. A migration failure stops startup instead of serving the new application against an old schema.
Choose Telemetry Storage#
Local DuckDB#
PROVON_TELEMETRY_DB_URL=duckdb:/srv/provon/telemetry.duckdbChoose DuckDB for the simplest fully local deployment. Keep the database on a local durable disk, not an eventually consistent network filesystem. One Node process should own the local file.
MotherDuck#
PROVON_TELEMETRY_DB_URL=motherduck:provon-telemetry
MOTHERDUCK_TOKEN=...Choose MotherDuck when telemetry should use managed remote storage while the Provon runtime remains self-hosted. Metadata, blobs, and local queue state still require durable Node storage.
Organization-isolated MotherDuck provisioning uses MOTHERDUCK_ADMIN_TOKEN; shared mode uses
MOTHERDUCK_TOKEN. Review the complete variables in
Self-hosting configuration.
Configure The Reverse Proxy#
Keep Workbench, API, Gateway, and OTLP on one public origin:
https://provon.example.com/
https://provon.example.com/v1/*
https://provon.example.com/gateway/v1/*
https://provon.example.com/api/auth/*The proxy must:
- terminate HTTPS;
- preserve request bodies and streaming responses;
- support WebSocket upgrades for realtime Gateway paths;
- set
X-Forwarded-Proto,X-Forwarded-Host, andX-Forwarded-Port; - allow the configured OTLP body-size ceiling;
- use timeouts suitable for long model responses.
Set PROVON_AUTH_TRUST_HOST=true only when the proxy overwrites forwarded headers and untrusted
clients cannot inject them. Set PROVON_WORKBENCH_ORIGINS to the exact browser origin.
OAuth callbacks use the public origin:
https://provon.example.com/api/auth/callback/github
https://provon.example.com/api/auth/callback/google
https://provon.example.com/v1/integrations/github/callbackVerify The Deployment#
Check runtime liveness:
curl --fail --silent https://provon.example.com/healthzThe response includes status, version, and deploymentTarget. This endpoint proves the HTTP
runtime is alive; it does not query every storage or provider dependency.
Then verify the product path:
- Sign in and create an organization and project.
- Create a project API key.
- Send one OTLP trace and confirm it appears in Traces.
- Send one Gateway request and confirm both the response and provider-attempt trace.
- Run one diagnostic Rule and inspect the Run.
- If enabled, connect GitHub and create one repair Issue from a supported Finding.
- Restart the process and confirm metadata, telemetry, blobs, and pending work remain available.
Use the Quickstart, Tracing quickstart, and Gateway quickstart for the request examples.
Scale And Availability#
The default Node deployment favors operational simplicity over horizontal availability.
- Run one active process.
- Use host or platform restart policy for process recovery.
- Put all local state on durable storage.
- Back up metadata, telemetry, blobs, and runtime state as one recovery set.
- Move telemetry to MotherDuck only when remote telemetry storage is useful; it does not externalize local queues.
- Choose the Cloudflare runtime when Gateway, ingest, and jobs must scale independently.