Configuration generator
Build a ready-to-paste configuration for a self-hosted Piwi Dashboard — as a .env file, systemd unit or shell exports; a Docker Compose service, docker run command or Kubernetes ConfigMap + Secret; or a hosting-platform manifest for Railway, Render, Fly.io, Koyeb or Coolify. Everything below is driven by the same typed registry as the configuration reference, so options, defaults and validation always match your server.
Start from a preset
Presets pre-fill a starting point (they combine). Piwi also runs with zero configuration — only set what you want to change.
Only variables understood by this server version are shown and emitted.
General0 set · 2 vars
Public base URL of the instance (e.g. https://piwi.example.com). Used to build links in emails. When unset, links in emails point to http://localhost:3000 and OAuth callback URLs are inferred from the request host — set it when running behind a reverse proxy.
Master key for AES-256-GCM encryption of secrets stored in the database (AI API keys, webhook/SCM secrets). Strongly recommended in production. Falls back to an insecure built-in development key (with a startup warning in production). Generate one with `node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"`.
Database0 set · 5 vars
Piwi uses SQLite by default. Setting `PIWI_DATABASE_URL` switches it to PostgreSQL; migrations run automatically on startup.
Path to the SQLite database file (used when PIWI_DATABASE_URL is not set).
PostgreSQL connection string. When set, PostgreSQL is used instead of SQLite and migrations run automatically on startup.
Days of test-run history the nightly retention sweep keeps. Unset or 0 disables automatic run pruning (the default — pruning is opt-in).
Days to keep sent/failed notification outbox rows before the nightly sweep prunes them (default 30; 0 keeps them forever).
AI-diagnosis history versions kept per diagnosis by the nightly sweep (default 20; 0 disables capping).
Storage0 set · 2 vars
Controls where test artifacts (HTML reports, traces, attachments) are stored.
Storage backend for test artifacts (HTML reports, traces, attachments): "local" or "s3". Only the exact value `s3` selects S3; any other value falls back to local storage.
Directory for local file storage (when PIWI_STORAGE_TYPE is "local").
Authentication0 set · 1 vars
Authentication is optional and off by default. When disabled, all endpoints behave as a single virtual administrator.
Set to "true" to enable role-based access control and API keys. Off by default.
Wasted time0 set · 1 vars
Controls which Playwright wait steps are counted as "wasted time" on the run timeline and in per-test/run totals. Classification happens when a run is viewed, so changing it re-classifies historical runs immediately.
Glob patterns (comma or newline separated) defining which wait steps count as wasted time. Locks the UI when set. Case-insensitive globs (`*` and `?`) matched against a wait step’s title or source location. Use `*` to count every wait.
AI diagnosis0 set · 1 vars
`PIWI_AI_PROVIDER` is the master switch: when it is set, AI configuration is environment-managed (the Settings UI shows the fields read-only) and the other `PIWI_AI_*` variables apply. When it is unset, AI diagnosis is configured from **Settings → AI** instead and the variables below are ignored.
AI provider for failure diagnosis: "anthropic" or "openai" (OpenAI-compatible).
AI context limits0 set · 24 vars
Cap how much evidence (and how many tokens) go into each AI diagnosis. Resolution order: defaults ← values stored from **Settings → AI** ← environment; the environment wins and locks the field in the UI. Values are clamped to the min–max range; a `0` disables a section only where the minimum is `0`.
Max characters of raw error text (per error block).
Total characters of diff patches across changed files.
Max affected tests listed in the diagnosis context.
Max recent test steps included.
Max console error/warning entries included.
Max characters per console entry.
Max failed network requests included.
Max characters of the page ARIA snapshot.
Max characters of the test source snippet.
Max full source files fetched from SCM to ground patches (0 disables).
Max characters per fetched full source file.
Max backend server log entries (from X-Piwi-Logs header) included.
Max characters per backend server log entry.
Max backend server spans (from X-Piwi-Trace header) included in AI diagnosis (0 disables).
Max screenshots auto-included in the diagnosis context.
Max peer tests in the same file listed when they passed.
Max console entries of any type in the window before failure.
Network request duration (ms) threshold for flagging as slow.
Max actions extracted from trace ZIP for failing-action context (0 disables).
Max characters for the trace-derived DOM/ARIA excerpt in failing-action context.
Max call-stack frames (with source windows) from the trace call-stack section (0 disables).
Max requests included from the trace network stream (0 disables).
Max characters of the failure-time DOM snapshot rendered from the trace (0 disables).
Screenshots are downscaled to at most this many pixels on the long edge before being sent.
Ingest limits0 set · 11 vars
Caps applied to per-execution payloads (console output, steps, ARIA snapshots, error text, source snippets) before they are stored. They bound database growth against verbose or hostile submitters; values above each limit are truncated with a visible marker. Distinct from the `PIWI_AI_MAX_*` limits, which bound what enters an AI diagnosis prompt — the storage defaults sit at or above the AI maxima so the AI limits stay the binding constraint for prompts. Environment-only (no settings UI).
Max console entries stored per test execution.
Max size of a single multipart upload (report upload or blob-report import), in bytes. Lower it to match a reverse proxy that rejects large bodies, so the import page rejects an oversized archive before uploading it.
Max characters stored per console entry.
Max test steps stored per execution.
Max step events stored per execution.
Max characters of the ARIA snapshot stored per failing execution.
Max characters of error text stored per execution (head and tail are kept).
Max characters of the sample error stored per failure cluster.
Max characters of the test source snippet stored per failing execution.
Max source stack frames stored per failing execution.
Max characters per stored source frame snippet.
Offline export0 set · 3 vars
Bounds on the offline export of a test execution or a failure cluster (HTML, ZIP, PDF). Evidence that does not fit is listed in the report as omitted rather than dropped silently. The total cap is also the memory an export costs to build, since the archive is assembled before it is sent.
Max size of a single evidence file embedded as a data: URI in an HTML export, in bytes. Larger files are left out of the single-file HTML (and listed as omitted); the ZIP export still carries them at full size.
Max total size of one export, in bytes. Evidence is added largest-last until the budget is reached; the rest is listed as omitted. The archive is built in memory, so this also bounds what a single export costs the server.
Max member executions carrying full evidence in a failure-cluster export. Remaining affected tests are listed by name without their evidence.
Timeline markers0 set · 1 vars
Automatically create a timeline marker when a run’s environment, Playwright version, or reporter version changes from the previous run (default: enabled). Set to false to disable. Only the exact value `false` disables auto-markers.
Email (SMTP)0 set · 1 vars
Required for email notifications and account flows (verification, password reset, invites). Set via environment only.
SMTP server hostname for outbound email.
Backend logs0 set · 1 vars
Controls the `X-Piwi-Logs` response-header capture that attaches backend logs to test failures. See [Backend logs](./backend-logs).
Disable X-Piwi-Logs response header emission (default: auto-disabled in production, enabled in development). Unset: capture is on in development and off in production builds; `true` forces it off everywhere, `false` forces it on even in production.