Self-hosted service
mysticaltech/terraform-hcloud-kube-hetzner avatar
mysticaltech/terraform-hcloud-kube-hetzner

Kube-Hetzner: Terraform for Kubernetes on Hetzner Cloud

Optimized and Maintenance-free Kubernetes on Hetzner Cloud in one command!

3,934 stars560 forksHCLMIT

At a glance

What is it?
A Terraform module that turns an empty Hetzner Cloud project into a k3s or RKE2 cluster on openSUSE Leap Micro. The defaults are opinionated, the upgrade path is documented, and the cost model is the reason most people look at it.
Who is it for?
Adopt Kube-Hetzner if you want a self-managed Kubernetes cluster on Hetzner Cloud and you are willing to run Terraform and read the docs before applying. Do not adopt it if you want a managed control plane, if you cannot tolerate the module's release cadence, or if your workload needs a cloud outside Hetzner.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly HCL, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Kube-Hetzner solves, and who it is for

Hetzner Cloud sells virtual machines, networks, load balancers and block storage. It does not sell a managed Kubernetes control plane. Anyone who wants Kubernetes there has to assemble the control plane, the CNI, the storage driver, the ingress controller, certificate management and the OS update path themselves. Kube-Hetzner is one Terraform module that does that assembly with defaults already chosen.

The README states the target plainly: a highly optimized, easy-to-operate Kubernetes cluster powered by k3s or RKE2 on openSUSE Leap Micro. The intended reader is an operator who is comfortable with Terraform and kubectl, not someone looking for a point-and-click console. The module creates the Hetzner project folder, writes a kube.tf, and then you deploy with tofu apply or terraform apply.

The cost argument is implicit in the topology table rather than spelled out. A three control plane, two agent production cluster on Hetzner is a different bill from a managed control plane on a larger provider, and the module's whole reason to exist is that you accept operating the control plane in exchange for that bill. If you are not willing to accept that trade, the module is the wrong shape of tool for you.

How the module is put together

The repository root is the module. control_planes.tf, agents.tf and autoscaler-agents.tf define the node groups; nat-router.tf handles private-only egress; tailscale.tf handles node transport; robot-nodes.tf covers Hetzner Robot dedicated machines; placement_groups.tf spreads nodes. Supporting files named validation-contract.tf and validation-locals.tf implement what the README calls plan-time guardrails: invalid topology and cross-variable combinations fail before infrastructure is created. That is a real design decision, because it moves a class of errors from a failed apply to a failed plan.

Configuration flows through variables.tf into kube.tf, and the outputs are described in docs/terraform.md. A values-merger.tf and values-export.tf pair suggests Helm values are assembled from several sources before being handed to the cluster, with kustomization_user.tf and kustomization_backup.tf providing the user and backup layers. The kustomize/ directory and the modules/ directory hold the pieces those files reference.

Networking is a first-class choice rather than a default you inherit: Flannel, Calico or Cilium, private-only NAT, dual-stack, Tailscale transport, and Gateway API. The README is explicit that Cloudflare Mesh and WARP are not supported as node transport, while Cloudflare Access and Tunnel are documented as an external boundary. That distinction matters when you are mapping your own access model onto the module.

Installing Kube-Hetzner and running a first apply

The README lays out four steps and names the prerequisites: OpenTofu or Terraform, Packer 1.16.0, kubectl and the hcloud CLI. With Homebrew the tooling install is one line.

bash
brew install opentofu kubectl hcloud

Packer is not in that command, so check your Packer version separately against 1.16.0 before you start; the README names that version explicitly. You also need a Hetzner Cloud project, a Read and Write API token, and a passphrase-less SSH key generated with ssh-keygen -t ed25519.

The bootstrap script is called createkh. It creates your project folder, a kube.tf, and the required Leap Micro images. The README gives this Bash or Zsh form, which downloads the script to a temporary file, makes it executable, and runs it with KH_SOURCE_DIRECTORY unset.

bash
(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")

After it finishes you edit kube.tf and remove the example node pools you do not need. The README then gives the deploy sequence, and notes that you use terraform instead of tofu if that is what you installed.

bash
cd <your-project-folder>
tofu init --upgrade
tofu plan
tofu apply

What you should see is a plan that lists the Hetzner resources the module will create for the topology you configured, followed by an apply that produces a kubeconfig you can use with kubectl. The README points at docs/terraform.md for every option, and at kube.tf.example as the reference configuration.

Picking a topology before you pick a node size

The README's topology table is the most useful page in the project, because it maps an operational need to a starting configuration instead of listing variables. A small development cluster is one control plane, one agent pool, and automatic upgrades disabled. Normal production HA is three control planes, two or more agents, one private Hetzner Network, and restricted API and SSH sources. Private-only clusters add a NAT router and a private control-plane load balancer. Tailscale node transport lets you close public API and SSH sources entirely.

Two entries deserve attention because they are the ones people get wrong. The first is the more than 100 cloud nodes case, which the README pairs with Tailscale multinetwork and explicit primary and external network scopes. The second is heavy image-pull pressure, which the README pairs with embedded_registry_mirror.enabled = true on a mutually trusted cluster. That qualifier is doing work: the mirror is not a general-purpose fix, it assumes a trust relationship between the clusters involved.

For Cilium Gateway API the README specifies Cilium with kube-proxy disabled and cilium_gateway_api_enabled = true, and points at examples/cilium-gateway-api/ as the starting point. The module also supports RKE2 as a first-class option for heavier and compliance-oriented environments, while k3s remains the lightweight default. Choosing between them is a decision you make in kube.tf, not something the module decides for you.

Where Kube-Hetzner is the wrong tool

The module builds and manages infrastructure. It does not manage your applications, and it does not give you a hosted control plane. If the control plane is the part you do not want to operate, no amount of Terraform in this repository changes that; you are looking for a managed Kubernetes service instead.

The provider lock-in is the second boundary. Everything here targets Hetzner Cloud, with robot-nodes.tf covering Hetzner Robot dedicated machines. If your architecture needs to span providers, or if you expect to move to another cloud later, the module's value shrinks because the cluster definition is written against Hetzner resources and a Hetzner Network model.

Upgrades are the third. The README advertises auto-upgrading, and it also ships docs/upgrades.md, a CHANGELOG.md, a 3.x upgrade guide and a MIGRATION.md for v2 to v3. That documentation exists because upgrades are not free. The release notes for v3.2.0 and v3.2.1 landed within about a week of each other in September 2026, and the repository's last push was on 2026-09-14. A fast release cadence is good for fixes and bad for anyone who wants to pin a version and forget it.

Finally, Cloudflare Mesh and WARP are explicitly not supported as node transport. If your access design depends on them, the module documents Cloudflare Access and Tunnel as the supported external boundary instead, and you should read examples/external-overlay-cloudflare-access/ before assuming the design will work.

How it differs from Talos on Hetzner

The closest alternative people search for is running Talos Linux on Hetzner with Terraform. The difference is the operating system and what that implies for day-2 work. Kube-Hetzner uses openSUSE Leap Micro as the default immutable node OS, with MicroOS still supported for existing clusters and explicit nodepool selection. Talos takes the API-driven, no-SSH approach, where the machine has no shell and all changes go through a machine config endpoint.

With Kube-Hetzner you keep SSH access to nodes, which the README treats as a first-class topic in docs/ssh.md, and you can use kustomization_user.tf and kustomize/ to layer your own manifests into the cluster. That is more surface area to manage and more ways to drift. It is also more room to debug a node that is misbehaving, which is the trade you are making.

The second difference is the upgrade story. Kube-Hetzner advertises auto-upgrading and documents OS updates and Kubernetes upgrades as integrated defaults, with docs/upgrades.md and examples/micro_os_rollback/ covering the rollback path. Talos handles upgrades through its own controller model. Neither approach is strictly better; they fail in different ways, and the one you pick should match how your team already operates machines.

Licence, maintenance and what an upgrade actually costs

The repository is MIT licensed. That permits commercial use and modification, and it means the module comes with no warranty. The README does not describe a paid support tier or a commercial edition, so the support model is the issue tracker and the documentation set. Nothing here is legal advice; read the LICENSE file yourself if the terms matter to your organisation.

Maintenance looks current rather than dormant. The last push was on 2026-09-14, and v3.2.1 was released on 2026-09-09, v3.2.0 on 2026-08-31 and v3.1.0 on 2026-08-08. That is three releases in roughly five weeks. The README also points at docs/v3-release-evidence.md, which ties release claims to live apply, upgrade, health and destroy evidence. That file is worth reading before you trust a version number, because it is the project's own statement of what was actually exercised.

The upgrade cost is the part to budget for. There is a 3.x upgrade guide and a MIGRATION.md for the v2 to v3 jump, which tells you major versions have required configuration changes. If you deploy this, record which version you applied, keep your kube.tf in version control, and read CHANGELOG.md before moving between minor releases rather than after.

Editorial conclusion

Adopt Kube-Hetzner if you want a self-managed Kubernetes cluster on Hetzner Cloud and you are willing to run Terraform and read the docs before applying. Do not adopt it if you want a managed control plane, if you cannot tolerate the module's release cadence, or if your workload needs a cloud outside Hetzner. Before your first apply, check the Packer version against the 1.16.0 the README names, confirm your node pools in kube.tf, and read docs/v3-release-evidence.md to see what the v3.2.1 claims are actually backed by.

Frequently asked questions

What is Kube-Hetzner and what does it deploy?

It is a Terraform module that deploys Kubernetes on Hetzner Cloud, using k3s as the lightweight default or RKE2 for heavier and compliance-oriented environments, on openSUSE Leap Micro nodes. The README describes it as production-ready Kubernetes with HA by default, auto-upgrading and cost-optimized.

How do I install Kube-Hetzner and create my first cluster?

Install OpenTofu or Terraform, Packer 1.16.0, kubectl and the hcloud CLI, then run the createkh bootstrap script, which creates your project folder, kube.tf and the required Leap Micro images. After editing kube.tf you run tofu init --upgrade, tofu plan and tofu apply from the project folder.

Does Kube-Hetzner support private-only clusters and Tailscale?

Yes. The README lists a private-only cluster as a NAT router plus a private control-plane load balancer, and Tailscale node transport as a way to close public API and SSH sources. It also states that Cloudflare Mesh and WARP are not supported as node transport.

Which CNI options does Kube-Hetzner offer?

The README lists Flannel, Calico and Cilium, alongside private-only NAT, dual-stack, Tailscale transport and Gateway API. For Cilium Gateway API it specifies Cilium with kube-proxy disabled and cilium_gateway_api_enabled = true.

Is Kube-Hetzner free to use?

The repository is MIT licensed, which permits commercial use and modification and comes with no warranty. You still pay Hetzner for the servers, networks, load balancers and storage the module creates.

Official sources

  1. Issues
  2. License: MIT
  3. mysticaltech/terraform-hcloud-kube-hetzner on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mysticaltech-terraform-hcloud-kube-hetzner.svg)](https://hysenlabs.com/projects/mysticaltech-terraform-hcloud-kube-hetzner)