Quickstart
Get a Kubernetes cluster running on Hetzner in about 15 minutes.
Prerequisites
A Hetzner Cloud account, and a project API token with Read & Write permission (Hetzner Console → Security → API tokens):
bashexport HCLOUD_TOKEN="<your-token>"The lok8s CLI: one self-contained command (installs the pinned toolchain into your project, nothing touches your system):
bashcurl -fsSL https://get.lok8s.io | sh -s -- -p kubeoneAlready using b? These two do the same:
bashb env add github.com/kernpilot/lok8s#kubeone b installAn SSH key pair (Ed25519 recommended)
A domain you control: the cluster’s API endpoint and certificate names are derived from it. You set it in step 1; the reference config ships
example.comas a placeholder, not a default.
1. Create your cluster config
lo keeps one folder per cluster, named after the cluster’s domain: clusters/<domain>/cluster.lok8s.yaml. Create the folder inside your project and save the file there:
mkdir -p clusters/example.com
# paste the file below into clusters/example.com/cluster.lok8s.yaml
lo use example.comlo use marks the domain as active, so every later command knows which cluster you mean.
# clusters/example.com/cluster.lok8s.yaml
apiVersion: cluster.lok8s.dev/v1beta1
kind: KubeOne
metadata:
name: my-cluster
spec:
kubernetes:
version: "v1.35.5"
cluster:
# REQUIRED: a domain you control; used for the API endpoint and cert names
domain: example.com
provider:
name: hetzner
# The machines, in Hetzner's own terms: each `server` entry becomes one
# `hcloud server create`, and its keys are hcloud flags. The role comes
# from the lok8s.dev/role label.
config:
cluster_name: my-cluster
sshUser: root
sshPrivateKey: ~/.ssh/id_ed25519
sshPublicKey: ~/.ssh/id_ed25519.pub
ssh-key:
- name: my-cluster
public-key-from-file: ~/.ssh/id_ed25519.pub
network:
- name: my-cluster
ip-range: 10.0.0.0/16
"#subnets":
- network-zone: eu-central
type: cloud
ip-range: 10.0.0.0/24
server:
# 1 control plane for dev; add two more for HA
- name: cp-1
type: cx33
image: ubuntu-24.04
# fsn1, nbg1, or hel1
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=control-plane
- name: worker-1
type: cpx31
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=worker
- name: worker-2
type: cpx31
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=workerChange domain (and the folder name) to a domain you control before the next step: nothing in this file can guess it for you. The three SSH paths assume a default-named Ed25519 key (~/.ssh/id_ed25519); if yours is named or stored differently, update those too.
2. Provision
lo provisionThis creates your control plane and worker nodes on Hetzner Cloud. The kubeconfig is written to .kubeconfig/my-cluster.yaml in your project, named after metadata.name. Your ~/.kube/config is never touched.
Provisioning typically takes 10–15 minutes. Hetzner bills the servers hourly (a small dev setup runs around €0.03/hour), and you can delete everything anytime with lo destroy.
3. Verify
kubectl still points at whatever context it used before, so select the new cluster explicitly; otherwise get nodes answers for your previous one:
export KUBECONFIG=.kubeconfig/my-cluster.yaml
kubectl get nodesYou should see your control plane and worker nodes in Ready state.
4. Register with kubehz (optional)
This step, and only this step, needs a free kubehz account; the prerequisites above are all the cluster itself requires.
Connect your cluster to the kubehz dashboard for read-only health visibility. Registration is outbound-only: kubehz never gets access into your cluster.
lo kubehz registerThis announces the cluster with the status Creating. Then claim it at app.kubehz.cloud to prove ownership and link it to your account (register → claim → owned). See Registration for the details and what the dashboard shows.
Next steps
- First Cluster walkthrough: detailed config reference
- Dashboard & account: explore the dashboard, access, and account
- How it works: the model, trust boundary, and your data
- Self-Hosted guide: advanced self-hosted setup
- Hosted control plane: the delegated path
Doc status
| Aspect | Detail |
|---|---|
| State | Live: matches the shipped CLI flow; provisioning duration is a conservative bound, not yet timed on the quickstart topology |
| Last reviewed | 5 September 2026 |