K8sCalc
kubernetes1 May 2026

Self-Hosted Kubernetes on Hetzner Cloud: Complete Setup Guide (2025)

A practical guide to running a production-grade HA Kubernetes cluster on Hetzner Cloud using kubeadm, HAProxy, Keepalived, and Longhorn — at a fraction of managed K8s cost.

Hetzner Cloud is one of the most cost-effective platforms for self-managed Kubernetes. A full HA production setup — 3 control planes, 3 workers, 2 HAProxy LB nodes — costs around €63/month, compared to €400–800/month for equivalent managed Kubernetes on AWS EKS or GKE.

This guide covers the complete setup: infrastructure, networking, control plane bootstrapping, and storage.

Architecture

Internet
    │
Floating IP (Keepalived VRRP)
    │
HAProxy-1 ←→ HAProxy-2   (active/passive)
    │
┌───┼───┐
CP1 CP2 CP3              (control plane, etcd)
    │
Worker-1 Worker-2 Worker-3

The Floating IP provides a stable entry point that survives HAProxy node failures. Keepalived runs VRRP between the two HAProxy nodes and moves the IP automatically on failure.

Server Sizing

For a standard production cluster:

RoleTypeCountCost
HAProxy / LBcx23 (2vCPU/4GB)2€7.98/mo
Control Planecx33 (4vCPU/8GB)3€19.47/mo
Workercx43 (8vCPU/16GB)3€35.97/mo
NetworkPrivate network + Floating IP€5.99/mo

Total: ~€69/month for a fully HA Kubernetes cluster.

Use the K8s Cluster Cost Calculator to price your specific configuration.

Step 1: Create the Infrastructure

Create a private network 10.0.0.0/16 in Hetzner, then create servers in the same network:

# Install hcloud CLI
brew install hcloud  # or: apt install hcloud

# Authenticate
hcloud context create k8s-prod

# Create private network
hcloud network create --name k8s-net --ip-range 10.0.0.0/16
hcloud network add-subnet k8s-net --type cloud --ip-range 10.0.1.0/24 --network-zone eu-central

# Create servers (example for LB nodes)
hcloud server create --name lb-1 --type cx23 --image ubuntu-24.04 --network k8s-net
hcloud server create --name lb-2 --type cx23 --image ubuntu-24.04 --network k8s-net

# Create and assign Floating IP
hcloud floating-ip create --type ipv4 --home-location fsn1
hcloud floating-ip assign <floating-ip-id> lb-1

Step 2: Configure HAProxy and Keepalived

On both LB nodes, install HAProxy and Keepalived:

apt-get install -y haproxy keepalived

Generate your haproxy.cfg using the HAProxy Config Generator, then configure Keepalived for VRRP failover.

The key Keepalived configuration uses a notify script to reassign the Hetzner Floating IP via the hcloud API on failover:

# /etc/keepalived/notify.sh
#!/bin/bash
ROLE=$3
if [ "$ROLE" = "MASTER" ]; then
  hcloud floating-ip assign <floating-ip-id> $(hostname)
fi

Step 3: Bootstrap the Control Plane

Generate a kubeadm config using the kubeadm Config Generator:

# On the first control plane node
kubeadm init --config kubeadm-config.yaml --upload-certs

The controlPlaneEndpoint must point to your Floating IP — this is the stable address all nodes use to reach the K8s API.

Step 4: Install a CNI

Flannel is the simplest option for Hetzner (no BGP required):

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

For NetworkPolicy support, use Calico instead (Flannel doesn't enforce policies).

Step 5: Add Worker Nodes

# Output from kubeadm init
kubeadm join 10.0.0.100:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

Step 6: Install Longhorn for Storage

helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set defaultSettings.defaultReplicaCount=3

Configure S3 backup to Hetzner Object Storage using the Longhorn S3 Backup Generator.

Cost vs Managed Kubernetes

PlatformEquivalent ConfigMonthly Cost
This setup (Hetzner)3 CP + 3 Workers HA~€69
AWS EKS3 × m5.xlarge workers~€450
GKE AutopilotEquivalent compute~€380
DigitalOcean DOKS3 × 4vCPU/8GB~€180

The tradeoff: you manage upgrades, cert renewal, and etcd backups yourself. Automate the etcd backups with the etcd Backup CronJob Generator.