Hetzner Cloud Provider

Deploy preview environments to Hetzner Cloud via SSH.

How it works

Prerequisites

  1. A Hetzner Cloud account and project.
  2. An SSH key pair — the public key registered in Hetzner, the private key stored in Previewops secrets.

Step 1 — Create a Hetzner API token

  1. Go to your Hetzner Cloud project → Security → API Tokens → Generate API Token.
  2. Select Read & Write permission.
  3. Store the token as HETZNER_API_TOKEN in Previewops secrets.

Step 2 — Register an SSH key in Hetzner

If you need a new key pair:

ssh-keygen -t ed25519 -C "previewops" -f ~/.ssh/previewops-hetzner
  1. Go to your project → Security → SSH Keys → Add SSH Key.
  2. Paste the contents of ~/.ssh/previewops-hetzner.pub.
  3. Give it a name (e.g. previewops) — this becomes sshKeyName in providerConfig.

Store the private key as HETZNER_SSH_KEY in Previewops secrets:

cat ~/.ssh/previewops-hetzner

Step 3 — Store secrets in Previewops

Secret Value
HETZNER_API_TOKEN API token from step 1
HETZNER_SSH_KEY PEM-encoded private key from step 2

Step 4 — Configure the repo

provider: hetzner
providerConfig:
  sshKeyName: previewops    # required — the exact name you gave the SSH key in Hetzner (step 2)
  serverType: cx22          # optional (default: cx22); run `hcloud server-type list` for all options
  location: nbg1            # optional (default: nbg1)
                            # options: nbg1 (Nuremberg), fsn1 (Falkenstein), hel1 (Helsinki),
                            #          ash (Ashburn, VA), hil (Hillsboro, OR), sin (Singapore)
  image: ubuntu-24.04       # optional (default: ubuntu-24.04)

Complete example with all options:

# .previewops.yaml
provider: hetzner
providerConfig:
  sshKeyName: previewops    # exact name of the SSH key registered in Hetzner (required)
  serverType: cx22          # server size (default: cx22 — 2 vCPU, 4 GB RAM, ~€0.005/hr)
  location: nbg1            # server location (default: nbg1)
  image: ubuntu-24.04       # OS image (default: ubuntu-24.04)

# Common options — all optional
concurrency: 3              # max simultaneous active previews per repo
ttlHours: 24                # auto-delete after N hours (default: 24)
port: 3000                  # optional — auto-detected from your Dockerfile EXPOSE; falls back to 8080
memory: 512Mi               # container memory passed to docker run (default: 512Mi)
cpu: 1                      # CPU shares passed to docker run (default: 1)
dockerfile: Dockerfile      # Dockerfile path relative to repo root (default: Dockerfile)
buildContext: .             # Docker build context (default: .)
env:
  NODE_ENV: preview         # inject env vars into the preview container

Step 5 — Verify

Comment /validate-previewops on any open PR. The bot calls the Hetzner API and confirms the token and SSH key name are valid.

Notes

Troubleshooting

Error Fix
HETZNER_API_TOKEN env var is required Set the token in secrets
HETZNER_SSH_KEY env var is required Set the private key in secrets
hetzner providerConfig.sshKeyName is required Add sshKeyName to providerConfig
SSH key not found from Hetzner API The name in providerConfig doesn't match the name registered in Hetzner
SSH connection refused Server hasn't finished cloud-init yet — the provider retries automatically