Configuration Reference
This document covers every field in .previewops.yaml and the runtime environment variables that affect your preview deployments. If you are self-hosting, see self-hosting.md for infrastructure setup.
.previewops.yaml
Place this file in the root of each repository you want to configure. All fields are optional — Previewops falls back to sensible defaults.
# Maximum simultaneous preview environments for this repo.
# When the limit is reached, the OLDEST preview is evicted automatically.
# Type: number Default: 3
concurrency: 3
# TTL before the preview is auto-deleted.
# Type: number (hours) Range: 1–720 Default: 24
ttlHours: 72
# Dockerfile path, relative to the repo root.
# Type: string Default: "Dockerfile"
dockerfilePath: Dockerfile
# Docker build context, relative to the repo root.
# Type: string Default: "."
buildContext: .
# HTTP port your container listens on.
# When omitted, previewops reads the first integer EXPOSE line from your Dockerfile
# and uses that port automatically. Falls back to 8080 if no EXPOSE is found.
# The PORT env var is injected into the container at runtime with the resolved value.
# Type: number Optional
port: 3000
# Container memory. Cloud Run values: 128Mi 256Mi 512Mi 1Gi 2Gi 4Gi 8Gi 16Gi 32Gi
# Type: string Default: 512Mi
memory: 256Mi
# Container CPU. Cloud Run values: 0.08 0.1 0.25 0.5 1 2 4 6 8 (fractional = shared)
# Type: string Default: 1
cpu: 0.5
# Environment variables injected into the preview container at runtime.
# Not for secrets — use Secret Manager + Workload Identity or your provider's credential store.
# See databases.md for database setup and authentication.md for auth patterns.
# Type: map<string, string> Default: {}
env:
NODE_ENV: preview
API_BASE_URL: https://api.staging.example.com
# Branches that auto-deploy when a push arrives and an open PR exists.
# No /deploy-previewops comment needed.
# Type: string[] Default: []
alwaysOn:
- staging
# Deploy provider. See providers/ for per-provider setup guides.
# Type: string Default: "cloud-run"
# Options: cloud-run fly hetzner docker-ssh render railway digitalocean
# aws-lightsail aws-ecs azure-container-apps
provider: cloud-run
# Non-secret structural config for the chosen provider.
# Type: object Default: {} (see providerConfig reference below)
providerConfig: {}
⚠️ Never put secrets in
env:. Values inenv:are committed to your git repository in plaintext and visible to anyone with read access to the repo. For database credentials, use the Preview DB add-on — it automatically injectsDATABASE_URLinto your container from an isolated preview database branch with no plaintext credentials in git. For other secrets, store them in the dashboard under Secrets & Environment Variables — encrypted at rest and injected automatically at deploy time (see credentials.md). Alternatively, use CLI mode with GitHub Actions secrets (e.g.${{ secrets.MY_SECRET }}) so values are resolved by GitHub before Previewops sees them and are never written to.previewops.yaml.
providerConfig reference
| Provider | Field | Type | Required | Default | Description |
|---|---|---|---|---|---|
fly |
orgSlug |
string | ✅* | — | Your Fly.io organisation slug. *Optional if FLY_ORG_SLUG is stored as a credential. |
fly |
region |
string | iad |
Fly.io region code. Overrides the FLY_REGION credential when set. |
|
hetzner |
sshKeyName |
string | ✅ | — | SSH key name as registered in Hetzner Console. |
hetzner |
serverType |
string | cx22 |
Hetzner server type. | |
hetzner |
location |
string | nbg1 |
Hetzner datacenter location. | |
hetzner |
image |
string | ubuntu-24.04 |
Server OS image. | |
docker-ssh |
host |
string | ✅ | — | SSH host (IP or hostname). |
docker-ssh |
user |
string | ubuntu |
SSH username. | |
docker-ssh |
port |
number | 22 |
SSH port. | |
docker-ssh |
baseDir |
string | /srv/previews |
Working directory on the remote host. | |
docker-ssh |
composeFile |
string | docker-compose.yml |
Compose file name. | |
docker-ssh |
baseUrl |
string | — | Public base URL of the server (HTTP). | |
render |
ownerId |
string | ✅* | — | Render owner/team ID (usr_… or tea_…). *Optional when RENDER_OWNER_ID is stored as a credential in the dashboard. |
render |
region |
string | oregon |
Render region. | |
render |
plan |
string | starter |
Render service plan. | |
railway |
projectId |
string | ✅* | — | Railway project UUID. *Optional when RAILWAY_PROJECT_ID is stored as a credential in the dashboard. |
railway |
environmentId |
string | ✅* | — | Railway environment UUID. *Optional when RAILWAY_ENVIRONMENT_ID is stored as a credential. Both IDs are visible in the Railway dashboard URL. |
digitalocean |
sshKeyId |
string | ✅ | — | Numeric ID of the SSH key in your DO account. |
digitalocean |
region |
string | nyc3 |
DO datacenter region slug. | |
digitalocean |
size |
string | s-1vcpu-1gb |
DO Droplet size slug. | |
aws-lightsail |
region |
string | us-east-1 |
AWS region. | |
aws-lightsail |
bundleId |
string | nano_2_0 |
Lightsail bundle (instance size). | |
aws-lightsail |
blueprintId |
string | ubuntu_22_04 |
OS blueprint. | |
aws-ecs |
cluster |
string | ✅ | — | ECS cluster name. |
aws-ecs |
vpc |
string | ✅ | — | VPC ID (vpc-…). |
aws-ecs |
subnets |
string[] | ✅ | — | Subnet IDs (at least one). |
aws-ecs |
securityGroups |
string[] | ✅ | — | Security group IDs (at least one). |
aws-ecs |
albListenerArn |
string | ✅ | — | ALB HTTPS listener ARN. |
aws-ecs |
executionRoleArn |
string | ✅ | — | ECS task execution role ARN. |
aws-ecs |
baseDomain |
string | ✅ | — | Previews served at pr-N.baseDomain. |
aws-ecs |
ecrRepoPrefix |
string | previewops |
ECR repository name prefix. | |
aws-ecs |
region |
string | us-east-1 |
AWS region. | |
azure-container-apps |
resourceGroup |
string | ✅ | — | Azure resource group. |
azure-container-apps |
managedEnvironment |
string | ✅ | — | Container Apps managed environment name. |
azure-container-apps |
acrServer |
string | ✅ | — | ACR login server (registry.azurecr.io). |
azure-container-apps |
registryName |
string | ✅ | — | ACR registry name (without .azurecr.io). |
azure-container-apps |
location |
string | eastus |
Azure region. |
QA testing: qa block
Controls the behaviour of /qa-previewops for this repository. All fields are optional.
qa:
# Controls Playwright draft generation for active QA scenarios.
# 'auto' (default): uses the org-level generate_drafts setting in the QA Hub dashboard.
# true: always generate drafts when the billing gate is met (QA Hub add-on + LLM + preview URL + active scenarios).
# false: never generate drafts — absolute deny, overrides the --generate-drafts CLI flag and org setting.
generateDrafts: auto
# Minimum scenario priority that marks the GitHub Check Run as action_required.
# 'p0' (default): only P0-impacted scenarios trigger action_required.
# 'p1': P0 or P1 impacted scenarios trigger action_required.
# 'p2': any impacted scenario triggers action_required.
# 'none': scenario impact never triggers action_required.
scenarioImpactCheck: p0
# Skip LLM analysis for this repo regardless of plan.
# Equivalent to always passing --coverage-only. No AI credits are consumed.
# Type: boolean Default: false
coverageOnly: false
Performance testing: performance block
Enable and configure load testing for your preview environments. See performance-testing.md for the full guide.
performance:
# Auto-run a perf test after every successful deploy (default: false)
enabled: false
# Virtual users (default: 10; capped by your plan — see performance-testing.md)
vus: 10
# Total test duration — s, m, or h (default: 30s; capped by your plan — see performance-testing.md)
duration: 30s
# Ramp-up period before reaching full VU count (default: 5s)
rampUp: 5s
# Optional: rate-limit requests per second
# targetTps: 100
# Base path prepended to all detected/configured endpoints
# apiBasePath: /api/v1
# Service Level Objectives — violations are warnings, not failures
slo:
p90: 400 # ms — p90 latency threshold (optional)
p95: 500 # ms — p95 latency threshold
p99: 1000 # ms — p99 latency threshold
errorRate: 0.05 # fraction — max error rate (default: 0.05)
# Explicit test scenarios (if omitted, endpoints are auto-detected from the diff)
scenarios:
- path: /users
method: GET
- path: /orders
method: POST
body: '{"item": "widget"}'
headers:
Content-Type: application/json
weight: 2 # relative frequency (default: 1)
# Use a custom k6 script from your repo (relative path)
# Pre-empts auto-generation; TARGET_URL is injected as __ENV.TARGET_URL
# scriptPath: k6/load-test.js
Preview DB: previewDb block
Controls how the Preview DB add-on injects the per-PR branch connection string. Requires the Preview DB add-on to be active.
previewDb:
# The environment variable to inject the per-PR preview database branch connection string into.
# Default: DATABASE_URL.
# Change this if your app already reads a different variable name, or if you want to
# preserve an existing DATABASE_URL you have set in the env: block above.
# PREVIEW_DB_URL is always injected as a stable alias regardless of this setting.
envVar: DATABASE_URL
Note: If
envVarmatches a key you have set in yourenv:block, Preview DB will overwrite that value with the branch connection string. A warning will appear in the PR dashboard comment. To preserve the original value, setenvVarto a different key.
Monorepo: services array
When your repository has multiple Dockerfiles, use services instead of top-level fields:
services:
- name: web # used as the service name suffix
dockerfilePath: apps/web/Dockerfile
buildContext: apps/web
port: 3000
memory: 256Mi
cpu: 0.5
env:
NEXT_PUBLIC_API_URL: https://api.preview.example.com
- name: api
dockerfilePath: apps/api/Dockerfile
buildContext: apps/api
port: 8080
memory: 128Mi
env:
LOG_LEVEL: debug # See databases.md for safe database access
Services are named prev-{owner}-{repo}-pr{pr}-{name} and all URLs are posted together in a single PR comment. Top-level fields (ttlHours, concurrency, provider, etc.) still apply; per-service fields override only the resource/dockerfile-related values.
Runtime environment variables
These variables affect deploy behaviour and can be set in your cloud provider's environment:
| Variable | Type | Default | Description |
|---|---|---|---|
PORT |
number | 8080 |
HTTP port the Express server listens on. |
GCP_REGION |
string | us-central1 |
GCP region used for Cloud Run and Artifact Registry. |
GCP_ARTIFACT_REGISTRY_REPO |
string | previewops |
Artifact Registry repository name for Docker images. |
DEFAULT_TTL_HOURS |
number | 24 |
Default preview TTL applied when .previewops.yaml has no ttlHours. |
DEFAULT_CONCURRENCY |
number | 3 |
Default max concurrent previews per repo when .previewops.yaml has no concurrency. |
DEFAULT_MEMORY |
string | 512Mi |
Default container memory allocation. |
DEFAULT_CPU |
string | 1 |
Default container CPU allocation. |
Provider credentials
Each provider requires specific credentials to be stored in the Previewops dashboard under Credentials. See credentials.md for how to add them, and the relevant provider guide for the exact keys required.