Bare Metal, Cloud, and Accelerators
A cloud VM and a rented dedicated server become identical nodes in your cluster. They run the same Syself Linux. The provisioner writes it, and the node joins the cluster the same way from either backend. The difference is how you get the machine and how you remove it.
Bare metal here is a dedicated server. You rent it from Hetzner through Robot, its interface for ordering servers, then register it with the platform. You are renting capacity in Hetzner's data centers. This is not hardware in your own building.
You can run your steady load on dedicated servers and add a cloud pool only for capacity that has to grow and shrink.
The same node from either backend#
A machine from either backend boots into the Hetzner rescue system, a minimal Linux used for disk-level installation. The provisioner writes Syself Linux to disk, verifies it, and reboots into the finished node.
Syself Linux is immutable. Its operating system cannot change after it is built. So there is nothing to patch on a running node, and you can verify that a node runs exactly what Syself shipped.
The same provisioner runs on both backends. It reads the hardware in rescue and gives a node only what it needs, so a GPU server and a plain cloud VM are built from the same image.
Because the image is the same, every node ships with the same software bill of materials (SBOM), the full list of what is installed on it. The Version Hub shows that list and its current CVE state, so you can see what is on a node and whether anything on it has a known vulnerability.
flowchart LR
subgraph elastic["Elastic: Hetzner Cloud"]
API["Hetzner Cloud API"] -->|"create / destroy"| HCM["HCloudMachine"]
end
subgraph fixed["Fixed pool: Hetzner Robot"]
Pool["HetznerBareMetalHost pool<br/>(rented servers: disk WWN, pool labels)"] -->|"claim / release"| HBM["HetznerBareMetalMachine"]
end
HCM --> Rescue["Hetzner rescue system:<br/>provisioner writes and verifies<br/>the immutable OS"]
HBM --> Rescue
Rescue -->|"boot"| Node["Same immutable Syself Linux node"]
Rescue -.->|"GPU detected in rescue"| GPU["GPU driver +<br/>NVIDIA device plugin"]
Rescue -.->|"KVM support detected<br/>(bare metal)"| Kata["secure runtime:<br/>runtimeClassName: secure"]
GPU -.-> Node
Kata -.-> NodeHow you get a machine and remove it#
The two backends use different models. Cloud creates and destroys machines. Bare metal claims and releases them.
Cloud is elastic. Syself calls the Hetzner Cloud API to create a server, and deleting the node deletes the server. There is always a spare to create, so cloud pools update without losing capacity: the new node joins before the old one drains. Healing works the same way. Reboot the server through the API, and if that does not fix it, delete the server and rebuild the node from the immutable image.
Placement groups add failure isolation. They tell Hetzner to put each cloud VM on a different physical host, so one host failure cannot take out several control-plane nodes at once (the control plane is the set of nodes that run Kubernetes itself). They are off by default, and you turn them on through the placement-group cluster variables .
Bare metal cannot work that way. You cannot create a Robot server with an API call. Instead the platform claims a server from a pool of servers you already rented, and releases it, wiped, when the node goes away. You register each rented server as a HetznerBareMetalHost, give it the WWN of the disk to install on (the WWN is a globally unique ID for a disk drive), and label it into a worker pool. Syself claims a free matching host, provisions it, and releases it when the node is removed.
| State | What happens |
|---|---|
| Free | Registered and free in the pool. |
| Preparing | Rebooted into rescue through the Robot API. |
| Inspecting hardware | Hardware details gathered: disks, network, GPU, KVM support. |
| Installing the image | The immutable OS is written and verified, with the parts the hardware needs. |
| Provisioned | Booted the immutable OS and joined the cluster. |
| Releasing, then free | Wiped and released, free to be claimed again. |
Healing and rollouts work the opposite way on bare metal. A bare-metal pool has no spare machine to create, so during an upgrade the old host drains and releases first, then gets reprovisioned. A pool at capacity runs one node short at each step. Keep a spare server free in the pool to avoid that.
| Cloud (elastic) | Bare metal (fixed pool) | |
|---|---|---|
| Get a node | API creates a server | Claim a free HetznerBareMetalHost |
| Remove a node | API deletes the server | Wipe and release the host to the pool |
| Rollout | New node joins first, then the old one drains | Old host is released first, then rebuilt |
| Unhealthy node | Reboot via API; if that fails, delete and recreate | Power-cycle via Robot; if that fails, release the host |
| Provisioning time | A few minutes | A few minutes, comparable to cloud |
Because the same physical machine is reused, its node name stays the same across reprovisions, so node-pinned local storage still points at its data.
Under the hood, a cloud node is an HCloudMachine and a bare-metal node is a HetznerBareMetalMachine bound to its host. You almost never touch these. You declare pools and sizes.
GPUs and secure workloads run on bare metal#
The immutable image comes up with only the parts a machine's hardware needs. When the provisioner inspects the hardware, it adds the driver or runtime that machine calls for. Two of these matter for choosing a backend: GPU support and the secure runtime.
A machine with an NVIDIA GPU comes up ready for GPU work, with the driver already in place and no manual install. You request a GPU in a pod and the scheduler places it on that node.
A bare-metal machine that supports virtualization gets the secure runtime class . Add runtimeClassName: secure to a pod and it runs in its own lightweight VM with a separate guest kernel. That isolation needs hardware virtualization, which only bare metal gives you.
A GPU server is registered, claimed, and provisioned like any other HetznerBareMetalHost. There is no separate image or pool type for it.
Why the base load runs on bare metal#
Bare metal and cloud suit different jobs. A dedicated server gives you physical cores instead of a shared slice, so it fits steady base load: databases on local NVMe (through TopoLVM, which you install), compute-heavy services, and GPU jobs. Cloud exists on demand and stops costing anything the moment you delete it, so it fits capacity that has to appear and disappear: burst and preview environments. The economics of owning vs renting covers the cost side.
Mixing the two is just separate worker pools in one cluster. The scheduler places each pod on the pool its requests and selectors match. Both pools give you the identical immutable node, so moving a stateless workload between them later just reschedules it, with no migration.
You can also skip cloud entirely. A bare-metal-only cluster works, load balancers included: a type: LoadBalancer Service and the control-plane endpoint both get a Hetzner Cloud load balancer that reaches the bare-metal nodes, with no extra setup.
The limits of bare metal#
A bare-metal node is one fixed physical machine you order ahead of time. It is slow to obtain, its local data is stuck on that machine, and a disk problem needs a different response than on cloud.
Bare metal is slow to get, but not slow to provision. Once you have the server, Syself provisions it in about the same time as a cloud server. The wait is in ordering: a Hetzner dedicated server can take a few hours to become available. So a pool that has to scale up and down in minutes belongs on cloud, not bare metal.
Local data is pinned to that machine. If you install TopoLVM, its volumes survive a reprovision of the same host but do not follow a workload rescheduled to a different server, so anything you cannot lose needs replication or off-node backups. The storage model covers how to place it.
Bare metal also handles a corruption signal differently. A cloud node reboots and replaces itself, because rewriting the image on a fresh VM is the fix. On bare metal the same failed disk-block read is as likely a dying disk as tampering, so a VerityCorruption escalates to a human instead of reprovisioning automatically.
Picking a backend per pool#
| You need | Use | Because |
|---|---|---|
| Databases and stateful services | Bare metal | Local NVMe through TopoLVM (you install it), no network hop, data survives reprovision of the same host |
Sustained compute, high RAM, GPU or secure workloads | Bare metal | Most hardware per euro; GPU and secure workloads need real hardware |
| Burst and scale-to-demand capacity | Cloud | Created and destroyed on demand through the API |
| Preview, dev, and test environments | Cloud | Short-lived by nature; delete the servers when done |
| Rollouts with no capacity dip | Cloud | A spare is always available, so the new node is created before the old one drains |
Where to go next#
When you are ready to put a rented server into a pool, Add Bare-Metal Servers walks through registering one as a HetznerBareMetalHost and labeling it into a pool. To go deeper on what the two node types mean for you:
The Storage Model
Syself Autopilot ships one storage backend, network-attached Hetzner Cloud volumes; local disks through TopoLVM are fast but pinned to one machine, so a database on local disk cannot move off that machine.
Minimal Provider Dependency
Syself Autopilot takes servers and load balancers from Hetzner and nothing else, and never builds a security boundary on the Hetzner private network.