Docker SSH Provider
Deploy preview environments to any server you can SSH into — bare metal, VPS, AWS EC2, GCP Compute Engine, etc.
How it works
- Build: SSHs into the server, clones (or pulls) the repo, and runs
docker compose build. - Deploy: runs
docker compose up -d. Each PR gets its own subdirectory underbaseDir. - Delete: runs
docker compose down --rmi localand removes the directory. - List: runs
docker ps --filter label=previewops=truevia SSH.
Prerequisites
- A server with Docker, Docker Compose v2, and Git installed.
- An SSH key pair with access to that server.
Step 1 — Prepare your server
# Install Docker (Ubuntu/Debian)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Install Git
sudo apt-get install -y git
The SSH user must be in the docker group (or be root).
Step 2 — Set up SSH key access
If you need a new key pair:
ssh-keygen -t ed25519 -C "previewops" -f ~/.ssh/previewops-ssh
Add the public key to the server:
ssh-copy-id -i ~/.ssh/previewops-ssh.pub user@your-server
Store the private key as SSH_PRIVATE_KEY in Previewops secrets:
cat ~/.ssh/previewops-ssh
Step 3 — Store secrets in Previewops
| Secret | Value |
|---|---|
SSH_PRIVATE_KEY |
PEM-encoded private key from step 2 |
Step 4 — Configure the repo
provider: docker-ssh
providerConfig:
host: 203.0.113.42 # required — SSH host (IP or hostname)
user: ubuntu # optional (default: ubuntu)
port: 22 # optional (default: 22)
baseDir: /srv/previews # optional (default: /srv/previews)
composeFile: docker-compose.yml # optional (default: docker-compose.yml)
baseUrl: http://203.0.113.42 # optional — publicly accessible URL prefix
# default: http://{host}
Step 5 — Verify
Comment /validate-previewops on any open PR. The bot opens an SSH connection, runs docker info, and reports success or failure.
Notes
- Each PR gets its own subdirectory:
{baseDir}/{owner}/{repo}/pr{number}/. - The preview URL is
{baseUrl}(defaults tohttp://{host}). If your compose service exposes a non-standard port, setbaseUrlinproviderConfigto include the port, e.g.http://203.0.113.42:3000. - Cost estimate in PR comments shows
N/A (your own infrastructure). - The server must have sufficient disk and memory for all concurrent previews — use
concurrencyin.previewops.yamlto cap them.
Using GCP free-tier Compute Engine
The e2-micro instance is always free in us-west1, us-central1, or us-east1:
gcloud compute instances create preview-server \
--machine-type=e2-micro \
--zone=us-central1-a \
--image-family=ubuntu-2404-lts-amd64 \
--image-project=ubuntu-os-cloud \
--tags=http-server
# Allow HTTP traffic
gcloud compute firewall-rules create allow-preview-ports \
--allow=tcp:1024-65535 \
--target-tags=http-server
Then follow steps 1–4 using the instance's external IP as host.
Troubleshooting
| Error | Fix |
|---|---|
SSH_PRIVATE_KEY env var is required |
Set the key in secrets |
docker-ssh providerConfig.host is required |
Add host to providerConfig |
Connection refused |
Check the server firewall / security group allows port 22 |
Permission denied (publickey) |
The public key isn't in ~/.ssh/authorized_keys on the server |
docker: command not found |
Docker isn't installed or the SSH user isn't in the docker group |
| Container exits immediately | Check logs with docker compose logs on the server |