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 [host firewall](/docs/hetzner/apalla/concepts/internals/networking), and the [mTLS tunnel each node opens to the control plane](/docs/hetzner/apalla/concepts/internals/platform-components). ```mermaid 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. [The security model](/docs/hetzner/apalla/concepts/ownership/security-model) 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. [Bare metal, cloud, and accelerators](/docs/hetzner/apalla/concepts/internals/bare-metal-and-cloud) 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. It initializes nodes. Every new node starts marked as not yet ready for the cloud, which keeps workloads off it. The CCM looks the server up, writes its Hetzner addresses and its provider ID onto the node, and clears the mark. A joining control plane waits several minutes for this. It cleans up. When a Hetzner server is deleted, the CCM deletes the matching `Node` object. It remembers Hetzner API answers for a few minutes, so that deletion can lag by that much. It runs load balancers. For each `type: LoadBalancer` Service it creates a Hetzner Cloud load balancer and writes its addresses back into the Service. [Networking](/docs/hetzner/apalla/concepts/internals/networking) covers how the load balancer answers traffic, which region it lands in, the proxy-protocol annotation, and how it reaches nodes. A companion `ccm-autoscaler` cluster component counts control-plane nodes and scales the CCM to match: one replica on a single-node control plane, two on a three-node HA one, so a new leader takes over quickly after a control-plane restart. ## 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 [the storage model](/docs/hetzner/apalla/concepts/internals/storage) 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: [the security model](/docs/hetzner/apalla/concepts/ownership/security-model) covers the full set of zero-trust layers, including the gaps you close yourself.