Hetzner Cloud Provider
Deploy preview environments to Hetzner Cloud via SSH.
How it works
- Build: SSHs into a fresh Hetzner server, clones the repo, and runs
docker build. Docker and Git are installed automatically via cloud-init on first boot. - Deploy: runs the built Docker image on the same server. Each PR gets its own server.
- Delete: deletes the Hetzner server via the Cloud API.
- List: lists all Hetzner servers with the label
previewops=true.
Prerequisites
- A Hetzner Cloud account and project.
- An SSH key pair — the public key registered in Hetzner, the private key stored in Previewops secrets.
Step 1 — Create a Hetzner API token
- Go to your Hetzner Cloud project → Security → API Tokens → Generate API Token.
- Select Read & Write permission.
- Store the token as
HETZNER_API_TOKENin 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
- Go to your project → Security → SSH Keys → Add SSH Key.
- Paste the contents of
~/.ssh/previewops-hetzner.pub. - Give it a name (e.g.
previewops) — this becomessshKeyNameinproviderConfig.
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 — name of SSH key registered in Hetzner (step 2)
serverType: cx22 # optional (default: cx22)
# see: hcloud server-type list
location: nbg1 # optional (default: nbg1)
# options: nbg1, fsn1, hel1, ash, hil, sin
image: ubuntu-24.04 # optional (default: ubuntu-24.04)
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
- Each PR gets its own server (
prev-{owner}-{repo}-pr{number}), provisioned on-demand and destroyed on delete/close. - First deploy takes ~2–3 minutes (server boot + cloud-init Docker installation). Subsequent deploys to the same PR reuse the server and are faster (~30 s).
- The preview URL is
http://{server-ipv4}. The container is mapped to port 80 on the host — no port number needed in the URL. For HTTPS, place Caddy or an nginx reverse proxy in front. - Hetzner pricing is among the lowest of any provider (~€0.005/hr for a cx22).
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 |