Self-hosting — browse guides

Self-hosting Vera

Run Vera on your own infrastructure: prerequisites, production build, the configuration that matters, backups, and the two settings to get right.

Vera runs on your own infrastructure. In self-hosted mode every feature is on — there is no plan gating and no billing — and no test data leaves your network.

What you need

  • Node 20 or newer, and pnpm
  • PostgreSQL — the single source of truth for projects, tests, runs and history
  • Playwright browsers, installed once
  • Optional: S3-compatible object storage for run artifacts (videos, screenshots, diffs). Without it, artifacts are written to local disk.
  • Optional: Google Chrome, if you want real Chrome mode

Development stack

The repository ships a compose file with Postgres and MinIO (an S3-compatible store):

docker compose up -d      # Postgres on :5439, MinIO on :9000 (console :9001)
pnpm setup                # install deps, build the DB package, install browsers
pnpm dev                  # API on :4545, dashboard on :4546

Production

pnpm install
pnpm playwright:install
pnpm build                # builds shared → db → server + dashboard
pnpm start                # serves the API and the built dashboard on one port (:4545)

pnpm start serves everything from a single origin — API, dashboard, and run artifacts — so there is no CORS configuration and no second deploy target.

Migrations are committed to the repository and applied automatically on startup, so a deploy does not need a separate migrate step.

Configuration

Every environment variable goes through one validated schema. .env.example documents all of them; these are the ones that matter first.

Required

VariablePurpose
DATABASE_URLPostgres connection string.
QA_AUTH_DUALWhether built-in auth runs alongside Clerk.
QA_BLOCK_PRIVATE_HOSTSWhether to refuse loopback/RFC1918 targets. See below.
QA_ALLOW_SETUP_COMMANDSWhether project setup actions may run shell commands.

Commonly set

VariablePurpose
PORT / HOSTWhere the server listens. Defaults to 127.0.0.1:4545.
QA_ENCRYPTION_KEYKey for sealing stored credentials and BYOK AI keys.
S3_*Object storage for artifacts. Omit to use local disk.
QA_MAX_BROWSERSCap on concurrent browsers process-wide.
CLAUDE_CLI_PATHPath to the claude binary, for the key-free AI provider.

Many runtime knobs are additionally admin-editable from the /admin console (browser cap, scheduler tick, recorder idle timeout, private-host policy, AI provider defaults) — env supplies the default, the database overlays overrides, and no restart is needed.

A few are deliberately env-only and cannot be changed over the API: the port and host, DATABASE_URL, the S3 credentials, the encryption key and CLAUDE_CLI_PATH. That last one names a binary the server spawns, so making it editable over HTTP would be a remote-code-execution vector.

Two settings to get right

HOST. The API has no authentication in local mode, so it binds 127.0.0.1 by default. Setting HOST=0.0.0.0 exposes it to the network — do that only where the network is trusted, or behind a reverse proxy that authenticates.

QA_BLOCK_PRIVATE_HOSTS. Vera navigates to URLs you give it, and testing your own app on localhost is the core use case, so loopback and private ranges are allowed by default. Cloud-metadata and unspecified addresses are always blocked. On a shared or multi-tenant host, set this to true — otherwise a tenant can point a test at your internal network.

Data & storage

WhatWhere
Projects, tests, runs, historyPostgres
Videos, failure screenshots, visual diffsS3, or data/ on local disk

Any S3-compatible store works. One flag matters and is easy to get wrong: S3_FORCE_PATH_STYLE. MinIO needs path style (endpoint/bucket/key) and is the default whenever S3_ENDPOINT is set; Railway Buckets, Tigris and AWS want virtual-hosted (bucket.endpoint/key) and need S3_FORCE_PATH_STYLE=false. Your store's own credentials page states which it requires — it is not safely inferable from the endpoint.

The server serves only the videos, screenshots and diffs subdirectories of the data directory. That is deliberate and worth preserving if you change it: serving the whole directory would expose anything else kept there.

Backups

Postgres holds everything that cannot be regenerated. pg_dump is safe while the server is running:

pg_dump "$DATABASE_URL" > vera-$(date +%F).sql

Restore into a fresh database and point DATABASE_URL at it. Artifacts are large and regenerable by re-running, so back them up only if run history matters to you as evidence.

The dump contains project credentials and sealed keys. Treat it as a secret.

Running hosted Vera rather than self-hosting? This section is the self-hosting answer, where you own the database and can decide a periodic dump is enough. The operator-side story — provider snapshots, PITR, artifact protection, RPO/RTO and a repeatable restore rehearsal — is disaster-recovery.md.

Whichever you run: sealed columns in the dump are AES-256-GCM, so restoring under a different QA_ENCRYPTION_KEY does not degrade gracefully — the rows restore fine and then every read of a credential throws. Back the key up somewhere that survives losing the machine, or the backup is only half a backup.

Keeping it running

Run it under whatever supervisor you already use — systemd, PM2, a container orchestrator. Two things to configure whichever you pick:

  • Graceful shutdown. On SIGINT/SIGTERM Vera stops the scheduler, ends recorder sessions, closes browsers, then closes the server, with a hard deadline. Give it a stop timeout of at least 15 seconds so in-flight runs finish writing rather than being killed mid-write.
  • Restart on failure, and start on boot.

Retention

Run retention is off by default: history accumulates until you set a policy. On a long-lived instance that is worth configuring — runs and their artifacts are the bulk of the storage growth. See Analytics.

AI

AI features are bring-your-own-key. Self-hosted, you can either configure a provider key or use the local claude CLI as a key-free provider by pointing CLAUDE_CLI_PATH at it. Nothing is sent to a Vera-operated service either way.

See also