Self-hosted service
syself/cluster-api-provider-hetzner avatar
syself/cluster-api-provider-hetzner

CAPH: running your own Kubernetes clusters on Hetzner through Cluster API

Cluster API Provider Hetzner :rocket: The best way to manage Kubernetes clusters on Hetzner, fully declarative, Kubernetes-native and with self-healing capabilities

1,140 stars113 forksGoApache-2.0

At a glance

What is it?
The Cluster API Provider Hetzner turns Hetzner servers into Kubernetes objects you can declare, so cluster lifecycle becomes a reconcile loop instead of a script. It is maintained by Syself and the community, not by Hetzner, and it expects a management cluster of your own.
Who is it for?
Adopt CAPH if you already run a Cluster API management cluster and want Hetzner cloud servers or dedicated bare metal to be described as custom resources, including the self-healing behaviour that comes with the reconcile loop.
Can I use it commercially?
Yes. Apache-2.0 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 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • syself/cluster-api-provider-hetzner1,140 ★ · +2
Star history
Repository2026-10-212026-11-07
syself/cluster-api-provider-hetzner1.1k1.1k

2 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Not an official Hetzner project, and that is stated up front

The first thing the README does is qualify the project. A note says the Cluster API Provider Hetzner is "independently maintained by Syself and the community", and that "It is not an official Hetzner project". Questions are directed to the GitHub Discussions tab or to `[email protected]`.

That distinction is not a formality, because the provider depends on Hetzner's own APIs. The dependency list in `go.mod` includes `github.com/hetznercloud/hcloud-go/v2` at v2.32.0 for the cloud API and `github.com/syself/hrobot-go` at v0.2.7, which is the client for the separate robot API that governs dedicated bare metal servers. Two different API surfaces, two different ways to provision a machine, and no official project behind the glue.

The licence is Apache-2.0, and the repository ships the Kubernetes-style Apache header in the Makefile. The provider is released under versions like v1.1.9, and the last push was on 2026-10-15, so the project is being worked on.

One commercial note belongs in any evaluation. The README says that if you want a batteries-included solution instead, you can try Syself, free for 14 days. CAPH is the DIY half of a business model, and that shapes who maintains it and how fast issues get attention.

Clusters become custom resources with a reconcile loop behind them

CAPH extends the Kubernetes API with Custom Resource Definitions, which the README describes as allowing you to interact with clusters "in the same fashion you interact with workload". The claim is that infrastructure and workloads are handled by the same tooling, and the repository layout supports it: the `api/` directory holds the type definitions, `controllers/` holds the reconcilers, and `config/` holds the CRDs and the RBAC manifests.

Three properties are listed. The first is self-healing: the CAPH and CAPI controllers "react to every change in your infrastructure, identifying and resolving issues without human intervention". The second is declarativeness, described as specifying a desired state and letting the operators do the rest, which the README links to repeatability and idempotency. The third is Kubernetes nativeness, meaning you can use tools you already know.

The self-healing claim is the one that changes day to day operations, and it is a direct consequence of the mechanism rather than a feature bolted on top. A controller watches a resource, compares the observed state against the desired state, and acts. A server that disappears, a node that fails to boot, a machine that was deleted in the Hetzner console, all become drift that a controller notices.

There is also a `templates/` directory in the repository, which is where the cloud-init or ignition content for provisioned machines usually lives, and a `data/` directory. The `PROJECT` file at the root and `metadata.yaml` are the Cluster API provider scaffolding files that identify the provider to `clusterctl`.

The getting started path runs through Kind and a community tutorial

The README does not contain a copy-paste quickstart. It points at three resources instead. The first is the Cluster API Provider Hetzner 15 Minute Tutorial in the documentation, whose stated purpose is to set up a bootstrap cluster using Kind and deploy a Kubernetes cluster on Hetzner. Kind is a local Kubernetes for development, and it is also visible in the dependency list as `sigs.k8s.io/kind` at v0.32.0, so the provider's own test infrastructure uses the same tool the tutorial recommends.

The second resource is a Hetzner Community Tutorials article titled "Managing Kubernetes on Hetzner with Cluster API". The README calls that the best way to get started, and a community tutorial hosted by the provider's own target cloud is a reasonable default ordering.

The third set of links is for developers rather than operators. A development guide introduces Tilt for "rapid testing of various cluster flavors, like with/without a private network or bare metal", and a separate topic page covers building your own node images for production systems. The repository backs this with a `Tiltfile` and a `tilt-provider.json` at the root, so the Tilt workflow is a supported development path rather than an experiment.

The practical consequence for an evaluating team is that the README will not give you the commands. They live in the documentation at caph.syself.com, and the documentation directory in this repository is where contributors edit them, which means the site and the code move together.

Bare metal and cloud servers arrive through two different clients

The provider's scope is wider than cloud instances on one platform. The dependency list shows `github.com/syself/hrobot-go`, the client for the robot API that Hetzner uses for dedicated servers, sitting next to `github.com/hetznercloud/hcloud-go/v2` for the cloud API. There is also `github.com/bramvdbogaerde/go-scp` at v1.5.0, an SSH copy implementation, which is consistent with pushing configuration onto machines that were created without a cloud-init payload.

A cluster made of dedicated bare metal servers is a different proposition from a cluster of cloud VMs, in cost, in control, and in how much of the work your team takes on. The README states the goal plainly: CAPH lets you have "DIY Kubernetes on Hetzner at any scale, with full control over your infrastructure and clusters configuration". The topics listed on the repository include `bare-metal` and `high-availability`, so both are part of the intended use.

Networking is where this gets a switch. The Makefile exposes a variable with a default that tells you what the default cluster looks like:

makefile
PRIVATE_NETWORK ?= false

The comment right above it points at the Hetzner cloud controller manager page on networks support. So a build of the provider defaults to not requiring a private network, and turning that on is a deliberate choice rather than a default. A cluster whose nodes talk to each other over public addresses is a different security and cost profile, and the variable is where that decision is made.

A CSR controller that signs kubelet certificates

One capability stands apart from the standard cluster lifecycle work, and the README gives it its own paragraph. The provider "can also validate and approve certificate signing requests", and the documentation link points to a page on the CSR controller.

The stated purpose is concrete: it increases security because the kubelets of the nodes can run with signed certificates, and it enables the metrics-server to run securely. A kubelet that presents a self-signed or anonymous certificate to the API server is a weak link in an otherwise standard cluster, and a controller that validates and approves certificate requests puts that step inside the same reconciliation loop as everything else.

The implementation is visible in the repository structure rather than in the README text. The `controllers/` directory sits alongside `pkg/`, and the Makefile provisions an image under the `ghcr.io/syself` prefix with the short name `caph`:

makefile
INFRA_SHORT = caph
IMAGE_PREFIX ?= ghcr.io/syself

The images are published to a container registry rather than only built locally, and the version of the builder image is pinned in a plain text file at the root, `.builder-image-version.txt`, which the Makefile reads with a shell command. Pinning a builder version in a tracked file is how you keep local builds reproducible against a moving base.

Node images must already contain kubeadm, kubelet and a runtime

This is the constraint that decides whether the project fits your setup. The README states that the provider "relies on a few prerequisites that must be already installed in the operating system images, such as a container runtime, kubelet, and kubeadm".

Reference images are said to be available in `kubernetes-sigs/image-builder`, which is the upstream project that produces the standard node images for Cluster API providers. If those prerequisites cannot be pre-installed, the README says custom scripts can be deployed through the kubeadm config, with a link into the node image topic of the documentation. That is a workable escape hatch, but it means the work of assembling a bootable image does not disappear, it moves to your pipeline.

The reason to be explicit about this is that it is the difference between a fifteen minute tutorial and a fortnight. A provider that can consume a ready image asks you for an image name. A provider that expects you to bake the prerequisites asks for a build pipeline, an image registry, a rebuild policy when the Kubernetes version moves, and a plan for what happens to existing nodes when the image changes.

The image reference is also where the version compatibility question comes back. The README states that the versioning for this project is tied to the versioning of Cluster API, and warns that the policy may change to align more closely with other providers in the ecosystem. The compatibility table itself lives in the documentation, at a path in this repository under `docs/caph/01-getting-started/01-introduction.md`.

The dependency set tells you what a CAPH upgrade costs

The `go.mod` file pins the versions that matter for an upgrade. The module is `github.com/syself/cluster-api-provider-hetzner` and it requires Go 1.25.12. The Cluster API libraries are `sigs.k8s.io/cluster-api` at v1.13.4 and the matching test module at the same version, with `sigs.k8s.io/controller-runtime` at v0.23.3 and the Kubernetes libraries at `k8s.io/api` and `k8s.io/client-go` version 0.35.5.

A provider that tracks Cluster API closely has a direct consequence for operators. When the Cluster API version moves, the provider version that supports it moves too, and a management cluster is normally shared by many providers. This is the compatibility table problem again, from the other side: the provider decides which Cluster API version it will accept, and your management cluster has to land on that version too.

The repository vendors its dependencies, with a `vendor/` directory at the root, which is the Cluster API provider convention and keeps the build independent of upstream module availability.

Testing follows the same convention. The `test/` directory and the `sigs.k8s.io/cluster-api/test` dependency, together with `ginkgo` and `gomega`, are the standard Cluster API provider test stack. The `hack/` directory holds the release and verification scripts, and the presence of `.mockery.yaml` says the interfaces are mocked with mockery rather than by hand.

When CAPH is the wrong tool

The clearest case is a team without a management cluster. CAPH is a Cluster API provider, so it runs as controllers inside a management cluster, which itself is a Kubernetes cluster to build, secure and upgrade. If you have one cluster and a desire for more, the overhead of standing up a bootstrap cluster with Kind and then running a provider inside it is heavy for a single workload.

The second case is wanting somebody else to answer for the control plane. The README itself points at that need by advertising the managed alternative, and an unmanaged DIY path means your team owns the provider upgrades, the node images, the etcd, and the cloud-init content in `templates/`.

The third case is a cloud-neutral requirement. The provider is for Hetzner, and the dependency list is Hetzner-specific at its core, with hcloud and hrobot clients. A project that must run the same cluster lifecycle across several clouds needs a different answer.

The fourth is a network layout that assumes private networking. The default of `PRIVATE_NETWORK ?= false` in the Makefile, together with the reference to the cloud controller manager networks support page, means you should check how the provider's network handling lines up with your firewall rules before committing to a topology, and the bare metal path through the robot API has its own provisioning cycle that the cloud path does not have.

Editorial conclusion

Adopt CAPH if you already run a Cluster API management cluster and want Hetzner cloud servers or dedicated bare metal to be described as custom resources, including the self-healing behaviour that comes with the reconcile loop. Do not adopt it if you want a managed control plane with someone else responsible for it, since the README points at Syself's commercial offering for that case, or if you are not prepared to keep node images current with a container runtime, kubelet and kubeadm baked in. Before you install, read the compatibility table in the documentation against the Cluster API version you run, and decide whether the default of `PRIVATE_NETWORK ?= false` is acceptable for your cluster layout.

Frequently asked questions

Is the Cluster API Provider Hetzner an official Hetzner project?

No. A note in the README states that it is independently maintained by Syself and the community, and that it is not an official Hetzner project. Questions are directed to the GitHub Discussions tab or to [email protected].

What do I need in a node image to use CAPH?

The README says the operating system images must already have a container runtime, kubelet and kubeadm installed. If that is not possible, custom scripts can be deployed through the kubeadm config, and reference images are said to be available in kubernetes-sigs/image-builder.

Does CAPH support dedicated bare metal servers?

The repository topics include bare-metal, the dependency list includes syself/hrobot-go, the client for the Hetzner robot API that governs dedicated servers, and the development guide describes testing cluster flavors with or without a private network or with bare metal.

How does CAPH handle kubelet certificates?

The provider includes a CSR controller that can validate and approve certificate signing requests, which the README says lets the kubelets of the nodes run with signed certificates and allows the metrics-server to run securely.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. syself/cluster-api-provider-hetzner on GitHub
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/syself-cluster-api-provider-hetzner.svg)](https://hysenlabs.com/projects/syself-cluster-api-provider-hetzner)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/syself-cluster-api-provider-hetzner.svg)](https://hysenlabs.com/projects/syself-cluster-api-provider-hetzner)

Was this useful?