Single-Location
Docker Compose deployment on a single serverEdit
Deploy Supercheck on a single server with Docker Compose.
Architecture
All services run on a single Linux server managed by Docker Compose. Workers consume jobs from Redis via BullMQ and execute each test as an ephemeral Kubernetes Job in a local K3s cluster, sandboxed with gVisor for kernel-level isolation. Scale by increasing WORKER_REPLICAS or expanding to multiple regions.
Docker Compose
Install Docker
A Linux server is required (Ubuntu 22.04+, Debian 12+). Supercheck uses K3s and gVisor for sandboxed test execution, which require the Linux kernel. macOS, Windows, and WSL2 are not supported.
# Review Docker's official installation script before running it.
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp dockerFor production hosts, you can instead follow Docker's distribution-specific Engine installation instructions to install from its package repository. Verify that docker compose version reports Compose v2 before continuing.
Clone and Configure
git clone https://github.com/supercheck-io/supercheck.git
cd supercheck/deploy/docker
./init-secrets.shEdit .env for optional integrations (SMTP, AI, OAuth). If you will open this HTTP deployment from another computer, also set the externally reachable origin (with no trailing slash):
NEXT_PUBLIC_APP_URL=http://YOUR_SERVER_IP:3000Set Up Execution Sandbox
sudo bash setup-k3s.shThis installs K3s with gVisor for sandboxed Playwright and K6 execution.
Deploy
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig docker compose up -dAccess
Open the URL configured in NEXT_PUBLIC_APP_URL and create your account. If you are working directly on the server and left the default unchanged, use http://localhost:3000.
# Optional: grant super admin
docker compose exec app node scripts/bootstrap-admin.js your-email@example.comInstall Docker
A Linux server is required (Ubuntu 22.04+, Debian 12+). Supercheck uses K3s and gVisor for sandboxed test execution, which require the Linux kernel. macOS, Windows, and WSL2 are not supported.
# Review Docker's official installation script before running it.
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp dockerFor production hosts, you can instead follow Docker's distribution-specific Engine installation instructions to install from its package repository. Verify that docker compose version reports Compose v2 before continuing.
Configure DNS
| Type | Name | Value |
|---|---|---|
| A | app | Your Server IP |
| A | * | Your Server IP |
The wildcard (*) record enables default status page URLs like abc123.example.com.
The same wildcard usually also covers the derived custom-domain target (for example, cname.example.com). If the target shown in Settings is outside that wildcard or on another zone, add an A/AAAA record for that target as well.
Customer-facing custom domains should stay outside the STATUS_PAGE_DOMAIN namespace. For example, you might reserve example.com for default UUID URLs and serve a status page at status.example.net by pointing its CNAME to cname.example.com.
Cloudflare Users: Set SSL/TLS mode to "Full" or "Full (Strict)".
Keep inbound TCP ports 80 and 443 open. Traefik uses port 80 for the ACME HTTP challenge and redirects HTTP traffic to HTTPS.
Clone and Configure
git clone https://github.com/supercheck-io/supercheck.git
cd supercheck/deploy/docker
./init-secrets.shEdit .env:
APP_DOMAIN=app.example.com
ACME_EMAIL=admin@example.com
STATUS_PAGE_DOMAIN=example.comSTATUS_PAGE_DOMAIN reserves the default status page namespace ([uuid].STATUS_PAGE_DOMAIN). In the HTTPS Compose examples, Supercheck derives the custom-domain target from it automatically, usually as cname.STATUS_PAGE_DOMAIN.
Set STATUS_PAGE_DOMAIN to a publicly reachable hostname. Keep customer-facing custom domains outside that reserved namespace, and keep those hostnames as CNAME records only. The target shown in Settings must already point to your app, usually via the wildcard * record above or a dedicated A/AAAA record for that target.
Local development still stays on http://localhost:3000/status/[subdomain]. STATUS_PAGE_DOMAIN is only used for public/default status-page hostnames once you access the app through that public hostname.
Set Up Execution Sandbox
sudo bash setup-k3s.shThis installs K3s with gVisor for sandboxed Playwright and K6 execution.
Deploy
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig docker compose -f docker-compose-secure.yml up -dAccess
Open https://app.example.com and create your account.
# Optional: grant super admin
docker compose -f docker-compose-secure.yml exec app node scripts/bootstrap-admin.js your-email@example.comUse docker-compose-external.yml when you want to connect Supercheck to managed external services (Neon, Supabase, Upstash, Cloudflare R2) instead of running PostgreSQL, Redis, and MinIO in Docker.
Configure External Services
Generate a secure .env, then replace its database, Redis, storage, and public URL values with your managed-service settings:
./init-secrets.sh
# Managed PostgreSQL (Neon, Supabase, RDS)
DATABASE_URL=postgresql://user:password@host:5432/supercheck
DB_HOST=host
DB_PORT=5432
DB_USER=user
DB_PASSWORD=password
DB_NAME=supercheck
# Managed Redis (Upstash, Redis Cloud)
REDIS_URL=redis://user:password@host:6379
REDIS_HOST=host
REDIS_PORT=6379
REDIS_PASSWORD=password
REDIS_TLS_ENABLED=true
# Managed S3-compatible storage (Cloudflare R2, AWS S3)
S3_ENDPOINT=https://your-account.r2.cloudflarestorage.com
AWS_REGION=auto
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
# Public HTTPS configuration
APP_DOMAIN=app.example.com
APP_URL=https://app.example.com
NEXT_PUBLIC_APP_URL=https://app.example.com
BETTER_AUTH_URL=https://app.example.com
STATUS_PAGE_DOMAIN=example.com
ACME_EMAIL=admin@example.comKeep the generated BETTER_AUTH_SECRET and SECRET_ENCRYPTION_KEY. For Redis providers that do not use TLS, set REDIS_TLS_ENABLED=false.
Set Up Execution Sandbox
sudo bash setup-k3s.shThis installs K3s with gVisor for sandboxed test execution.
Start Services
# Create .env with your managed service credentials
# Use the template below or start from the compose file's documented variables
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig docker compose -f docker-compose-external.yml up -dThis compose file skips the bundled PostgreSQL, Redis, and MinIO containers. It starts the App, Worker, and Traefik containers; the Worker submits sandboxed jobs to the host K3s cluster.
Optional Configuration
Operations
Scaling
WORKER_LOCATION=local (default) processes all queues on a single server. The UI auto-hides location selectors when only one location exists. Expand later via Multi-Location Workers.
# Quick Start (HTTP):
WORKER_REPLICAS=2 RUNNING_CAPACITY=2 QUEUED_CAPACITY=20 \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose up -d
# Production (HTTPS):
WORKER_REPLICAS=2 RUNNING_CAPACITY=2 QUEUED_CAPACITY=20 \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose -f docker-compose-secure.yml up -d| Size | Workers | Capacity | Server |
|---|---|---|---|
| Small | 1 | 1 | 2 vCPU / 4GB |
| Medium | 2 | 2 | 4 vCPU / 8GB |
| Large | 4 | 4 | 8 vCPU / 16GB |
RUNNING_CAPACITY and QUEUED_CAPACITY are enforced by the App. Set them in .env; workers may receive the shared values but do not use them. WORKER_REPLICAS controls the number of worker containers. Keep RUNNING_CAPACITY equal to the total number of worker replicas.
Backups
docker compose exec postgres sh -c 'pg_dump -U "$DB_USER" "$DB_NAME"' > backup.sql # Create
docker compose exec -T postgres sh -c 'psql -U "$DB_USER" "$DB_NAME"' < backup.sql # RestoreUpdates
Images are pinned to a specific release through SUPERCHECK_VERSION, which defaults to the release bundled with this Compose file. Set it in .env to upgrade, and keep the App and Worker on the same value so the execution sandbox cannot drift from the control plane.
# In .env: set the target release (see GitHub Releases for available tags)
SUPERCHECK_VERSION=1.3.6Then pull and restart:
# Quick Start (HTTP):
docker compose pull && \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose up -d
# Production (HTTPS):
docker compose -f docker-compose-secure.yml pull && \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose -f docker-compose-secure.yml up -dUpgrading from pre-1.3.3 releases — Supercheck moved from Docker socket-based test execution to a sandboxed K3s + gVisor model in 1.3.3. Before upgrading an older deployment, you must run the setup script:
# 1. Back up your database first
docker compose exec postgres sh -c 'pg_dump -U "$DB_USER" "$DB_NAME"' > backup-pre-k3s-migration.sql
# 2. Install K3s + gVisor execution sandbox
sudo bash setup-k3s.sh
# 3. Pull new images and restart with kubeconfig
# Quick Start (HTTP):
docker compose pull && \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose up -d
# Production (HTTPS):
docker compose -f docker-compose-secure.yml pull && \
KUBECONFIG_FILE=/etc/rancher/k3s/supercheck-worker.kubeconfig \
docker compose -f docker-compose-secure.yml up -dThe worker container no longer requires the Docker socket. Existing tests and monitors continue to work without modification. If you have remote workers (Multi-Location), run setup-k3s.sh on each remote server as well.