Skip to main content

Minimal Provider Dependency

Inspect 1.36

Syself Autopilot takes two things from Hetzner: servers and load balancers, and nothing else. No private network, no VPC, no managed services for identity, routing, or isolation.

Most managed Kubernetes depends on the cloud's own network and services. The nodes trust each other because they share a private subnet. The control plane (the nodes that run Kubernetes itself) runs inside the provider's VPC. Identity, routing, and isolation come from the provider's managed services. These pieces are provider-specific, so moving to another provider means building them again.

Syself takes the opposite approach. The tables below show what it takes from Hetzner and what it leaves out.

Depends on Hetzner for What it is
Cloud servers Virtual machines created and destroyed through the Hetzner Cloud API.
Robot dedicated servers The bare-metal pool you claim, provision, and release.
Cloud load balancers (via the ccm cluster component) A public endpoint for the control plane, and one load balancer per type: LoadBalancer Service.
Not built on Why
The Hetzner private network, or any VPC-style boundary Drops packets silently at scale; unreliable.
Provider-managed platform services Syself runs its own software above the machines, so it adds no provider-specific dependency.

Each node protects itself in software: the immutable node OS, the node agent, the , and the .

flowchart LR
  subgraph hz["Hetzner: the whole dependency"]
    srv["Servers: Cloud VMs and Robot bare metal"]
    lb["Cloud load balancers, created by the ccm cluster component"]
    pn["No private network: not used, never a security boundary"]
  end
  subgraph net["Public internet, untrusted"]
    node["Immutable node, host firewall"]
    cp["Control plane"]
  end
  srv -->|"machines to run on"| node
  lb -->|"public traffic in"| node
  node -->|"mTLS tunnel"| cp
  pn -.->|"not attached"| node

Why the private network is not used#

The Hetzner private network is unreliable. At scale it drops packets with no error. The problem does not show up until something built on top of it fails, and the cause is then hard to trace. It caps at 100 servers, has problems on vSwitch (Hetzner's virtual-switch feature) and older hardware, and is IPv4 only.

It is also not a VPC, though people expect it to be. On AWS or GCP a VPC walls your network off from other tenants, and you decide what may reach what with rules the provider guarantees. Hetzner's private network only hands your servers addresses on a shared network so they can find each other. It gives no isolation and no encryption, so it cannot be a security boundary.

A private network would not improve security, because the cluster is already safe without it. explains why.

A cluster cannot add a private network#

A cluster that asks for a private network is rejected when it is applied. There is nothing to switch on.

Warning

Do not set load-balancer.hetzner.cloud/use-private-ip: "true" on a default cluster. It targets nodes by their private-network IP, and a default cluster has no private network. The Service looks healthy, but no traffic arrives.

Losing the private network costs you nothing here. You still get the load balancer, and it reaches Cloud and bare-metal nodes the same way, so a type: LoadBalancer Service works even on a bare-metal-only cluster. covers how each backend is reached.

The ccm cluster component and its calls to Hetzner#

A running cluster calls the Hetzner Cloud API from one component, the cloud-controller-manager (the ccm cluster component, pinned to control-plane nodes). It gives each new node its Hetzner addresses and provider ID, deletes the Node object when the server behind it is deleted, and sets up a Hetzner load balancer for every type: LoadBalancer Service.

Pod-network routing is not one of these calls; Cilium handles the datapath. At runtime a cluster needs only a small part of the Hetzner API: read server metadata, and manage load balancers.

Where storage lives#

Storage attaches to the machine, not to a shared network. A cloud node uses Hetzner Cloud block volumes. A bare-metal node uses its own local disks. Either way there is no shared network fabric you would have to rebuild somewhere else. See for where data lives and how it survives a node replacement.

Support for other providers#

The software layers above the machines assume no provider-specific network. The same cluster design can run on more than one provider. Today the platform is integrated closely with Hetzner, and support for more providers is planned.

Even the dependency on Hetzner load balancers can be dropped (planned). A bare-metal server could serve the control-plane endpoint on its own, without the load balancer's high availability. That leaves the servers as the only thing Syself takes from the provider.

Networking is the hard part of supporting more providers. Cilium, the kernel modules it loads, how Kubernetes moves packets, and what the immutable OS exposes must all be compatible. Changing a few Cilium values is not enough, so Syself integrates and tests these layers together.

Next: covers the full set of zero-trust layers, including the gaps you close yourself.