HA by default | Auto-upgrading | Cost-optimized
A highly optimized, easy-to-operate Kubernetes cluster powered by k3s or RKE2 on openSUSE Leap Micro, deployed on Hetzner Cloud.
Go from an empty Hetzner project to a running cluster in four steps.
- Production-ready defaults: private networking, firewalls, CSI storage, ingress, certificate management, OS updates, and Kubernetes upgrades are integrated.
- k3s or RKE2: k3s is the lightweight default; RKE2 is a first-class option for heavier and compliance-oriented environments.
- Highly available and elastic: odd control-plane quorum, multi-location pools, static agents, and Cluster Autoscaler nodepools.
- Immutable openSUSE nodes: Leap Micro is the default; MicroOS remains supported for existing clusters and explicit nodepool selection.
- Flexible networking: Flannel, Calico, or Cilium; private-only NAT; dual-stack; Tailscale transport; Gateway API; and advanced multinetwork designs.
- Plan-time guardrails: invalid topology and cross-variable combinations fail before infrastructure is created.
- Evidence-backed releases: release claims are tied to live apply, upgrade, health, and destroy evidence in
docs/v3-release-evidence.md.
Current release: v3.1.0 release notes | Changelog | v2 to v3 migration
-
Install OpenTofu or Terraform, Packer 1.16.0, kubectl, and hcloud. With Homebrew, install the other tools in one command:
brew install opentofu kubectl hcloud
-
Create a Hetzner Cloud project, create a Read & Write API token, and generate a passphrase-less SSH key (
ssh-keygen -t ed25519). -
Run
createkh. It creates your project folder,kube.tf, and the required Leap Micro images.Bash/Zsh:
(tmp_script=$(mktemp) && trap 'rm -f "$tmp_script"' EXIT && curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/create.sh && chmod +x "$tmp_script" && env -u KH_SOURCE_DIRECTORY "$tmp_script")
Fish:
set tmp_script (mktemp); curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/create.sh; and chmod +x "$tmp_script"; and env -u KH_SOURCE_DIRECTORY bash "$tmp_script"; set run_status $status; rm -f "$tmp_script"; test $run_status -eq 0
-
Edit
kube.tf, remove example node pools you do not need, then deploy:cd <your-project-folder> tofu init --upgrade tofu plan tofu apply
Use
terraforminstead oftofuif that is what you installed. Every option is listed in the generated configuration reference.
| Need | Recommended starting point |
|---|---|
| Small development cluster | One control plane, one agent pool, automatic upgrades disabled. |
| Normal production HA | Three control planes, two or more agents, one private Hetzner Network, restricted API and SSH sources. |
| Private-only cluster | NAT router plus a private control-plane load balancer. |
| Secure operator access | Tailscale node transport with public API and SSH sources closed. |
| More than 100 cloud nodes | Tailscale multinetwork with explicit primary/external network scopes. |
| Cilium Gateway API | Cilium, kube-proxy disabled, and cilium_gateway_api_enabled = true. |
| Heavy image-pull pressure | embedded_registry_mirror.enabled = true on a mutually trusted cluster. |
Read the topology recommendations and support matrix before choosing an advanced path.
Cloudflare Access/Tunnel is a documented external boundary for operator and application access. Cloudflare Mesh/WARP is not supported as kube-hetzner node transport. See the Cloudflare external-access example. For Gateway API, start with the Cilium example.
docs/index.md is the complete documentation map. Start with the path that matches your task:
| Task | Read this |
|---|---|
| Configure a cluster | kube.tf.example, Terraform inputs and outputs, operator reference |
| Operate a cluster | Day-2 operations, SSH and access, backup and restore |
| Upgrade Kubernetes, the OS, or the module | Upgrades |
| Debug a broken cluster or expired certificates | Troubleshooting |
| Copy a working configuration pattern | Recipes and examples/ |
| Design networking or private egress | Topology recommendations, private-network egress |
| Review security and artifact trust | SELinux, installation supply chain |
| Add a Hetzner Robot server | Dedicated server integration |
Do not blind-apply a v2 to v3 upgrade. Start with MIGRATION.md for the compatibility contract and variable map, then follow the step-by-step migration guide. Back up state and reject any plan with unexplained destroy or replacement actions.
The fastest assisted path is /migrate-v2-to-v3, which rewrites the configuration and runs the protected-infrastructure plan gate without applying changes.
Install the project skills in Claude Code, Codex, Cursor, or another skills-compatible agent:
npx skills add kube-hetzner/terraform-hcloud-kube-hetzner| Skill | Purpose |
|---|---|
/kh-assistant |
Configuration and troubleshooting help grounded in the current repository. |
/migrate-v2-to-v3 <terraform-root> |
Guided migration with protected-infrastructure plan review. |
/upgrade-cluster <terraform-root> |
Safety-first module and Kubernetes upgrade workflow. |
/debug-node <server> |
Rescue workflow for unreachable nodes, SSH, cloud-init, and provisioning failures. |
/test-changes |
Repository-native Terraform/OpenTofu validation gates. |
Use the state-aware destroy wrapper first. It handles known dependency races and reports possible Hetzner orphans without deleting them outside Terraform:
(tmp_script=$(mktemp) && trap 'rm -f "$tmp_script"' EXIT && curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/destroy.sh && chmod +x "$tmp_script" && "$tmp_script")Forceful cleanup fallback:
(tmp_script=$(mktemp) && trap 'rm -f "$tmp_script"' EXIT && curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/cleanup.sh && chmod +x "$tmp_script" && "$tmp_script")Warning
cleanup.sh can delete every matching server, network, load balancer, placement group, SSH key, and volume. Review its dry run before confirming.
Fish shell version
set tmp_script (mktemp); curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/cleanup.sh; and chmod +x "$tmp_script"; and bash "$tmp_script"; set run_status $status; rm -f "$tmp_script"; test $run_status -eq 0Save as cleanupkh (Bash/Zsh)
cleanupkh() { (tmp_script=$(mktemp) && trap 'rm -f "$tmp_script"' EXIT && curl -fsSL -o "$tmp_script" https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/scripts/cleanup.sh && chmod +x "$tmp_script" && "$tmp_script"); }Hetzner Cloud provides high-value infrastructure across Europe and the US. Kube-Hetzner combines it with:
- openSUSE Leap Micro, an immutable OS with transactional updates and BTRFS rollback.
- k3s, a lightweight certified Kubernetes distribution with integrated operational components.
- RKE2, a hardened Kubernetes distribution for heavier deployments.
- Terraform and OpenTofu, keeping infrastructure explicit, reviewable, and reproducible.
Kube-Hetzner is not affiliated with Hetzner.
Questions, ideas, and community support belong in GitHub Discussions. Issues and pull requests are welcome. For contribution setup and repository gates, read CONTRIBUTING.md.
Kube-Hetzner is free and open source. If it saves you engineering time or infrastructure cost, please help fund its continued development.
Sponsorship directly supports issue response, new capabilities, documentation, security maintenance, and real-cluster release testing.
Every contribution helps keep Kube-Hetzner reliable, current, and available to everyone.
- k-andy, the starting point for this project.
- Rancher, for k3s and RKE2.
- openSUSE, for Leap Micro and MicroOS.
- HashiCorp and OpenTofu, for the infrastructure tooling ecosystem.
- The contributors and operators who report issues, improve the module, and test real upgrades.
Released under the MIT License.