Hetzner
This guide walks through deploying NKP on Hetzner Cloud with nic (the Nebari Infrastructure Core CLI), from an empty Hetzner account to a running cluster you can manage and tear down.
Hetzner is the recommended starting point for most teams: it is the cheapest production-capable provider supported by NKP, offers EU data residency (GDPR-friendly locations in Germany and Finland), and requires no IAM policies, NAT gateways, or managed-Kubernetes fees — just servers, one load balancer, and block volumes.
What your team gets
When nic deploy finishes, your team will have all standard NKP services plus:
- A k3s Kubernetes cluster ready for workloads (single-node or multi-node, your choice).
- Shared RWX storage that pods on any node can mount (Longhorn, installed automatically — Hetzner's native CSI is read-write-once only).
Prerequisites
Hetzner Cloud account
You'll need a Hetzner Cloud account. If you don't have one, sign up at console.hetzner.cloud.
- Location: pick a datacenter where you want your cluster. Choose from one of the availability zones.
- Cost: Hetzner Cloud has no free tier; servers, load balancers, and volumes all bill from the moment they're created.
API token
nic authenticates to Hetzner using a project-scoped API token:
- Open console.hetzner.cloud, select your project, and go to Security → API Tokens.
- Click Generate API token, give it a description (e.g.,
nic-deploy), and choose Read & Write. - Copy the token immediately — it is shown only once.
You'll add this token to your .env file. See the Secrets and credentials section below for details.
Install nic
Follow the Install NIC guide to download and install the nic CLI for your platform.
GitOps repository
See GitOps repository in the Prepare to deploy guide.
Secrets and credentials
From inside your GitOps repo clone, download the template:
cd /path/to/your-gitops-repo
curl -o .env https://raw.githubusercontent.com/nebari-dev/nebari-infrastructure-core/main/.env.example
Then uncomment and fill in the Hetzner token and GitOps tokens. For .gitignore setup and GitOps token configuration, see Secrets and credentials in the Prepare to deploy guide.
# Hetzner Cloud
HETZNER_TOKEN=your-hetzner-api-token
Cost considerations
A NKP deployment on Hetzner Cloud provisions three categories of resources that bill from day one. Check Hetzner's pricing page for current rates.
- Servers: per-hour billing for each node. The examples below use
cpx31(4 vCPU / 8 GB RAM AMD), which strikes a good balance between price and capacity. Master nodes and worker nodes use the same type by default. - Load balancer:
niccreates one Hetzner LB for cluster ingress. Flat hourly rate plus traffic. - Block volumes: Longhorn uses Hetzner block volumes for persistent storage. Per-GB-month billing.
Hetzner is significantly cheaper than equivalent AWS deployments because there is no managed Kubernetes control-plane fee, no NAT gateways, no VPC interface endpoints, and no per-mount-target EFS charge. A minimal three-node cpx31 cluster (one master, two workers) plus one load balancer typically costs a fraction of an equivalent EKS setup.
Configuration
Download the starter config from the nebari-infrastructure-core:
curl -O https://raw.githubusercontent.com/nebari-dev/nebari-infrastructure-core/main/examples/hetzner-config.yaml
In later steps, <config-file> refers to this local copy (hetzner-config.yaml).
At minimum, edit these fields:
project_name: my-cluster # lowercase alphanumeric, hyphens, underscores
domain: nebari.example.com # a hostname you own
certificate:
type: letsencrypt
acme:
email: you@example.com # required for Let's Encrypt; renewal notices go here
git_repository:
url: "https://github.com/<your-org>/<your-gitops-repo>.git"
path: clusters/my-cluster # subdirectory in the repo; conventionally matches project_name
auth:
token_env: GIT_TOKEN # matches GIT_TOKEN set in .env
cluster:
hetzner:
kubernetes_version: "1.32"
# REQUIRED: datacenter location.
location: fsn1
node_groups:
# Exactly one node group must have master: true.
# Count must be odd (1, 3, 5) when running HA embedded etcd.
master:
instance_type: cpx31 # 4 vCPU / 8 GB — good general-purpose starting point
count: 1
master: true
workers:
instance_type: cpx31
count: 2
For more configuration options, see the Hetzner provider reference.
For the full schema (autoscaling, persist_data, Longhorn options), see the NIC configuration reference.
Deploy
Run the deploy commands as described in Deploy and verify in the deploy lifecycle guide. Allow 10–15 minutes for the first deployment — k3s cluster creation followed by ArgoCD syncing foundational services.
See DNS in the deploy lifecycle guide for DNS setup (Cloudflare or manual A record). For full DNS configuration options, see the NIC DNS configuration reference.
Verify
nic writes the kubeconfig to ~/.cache/nic/hetzner-k3s/<project_name>/kubeconfig. Point kubectl at it:
export KUBECONFIG=~/.cache/nic/hetzner-k3s/<project_name>/kubeconfig
Then follow the Deploy and verify steps in the deploy lifecycle guide to check the cluster and ArgoCD applications.
First sign-in
See First sign-in in the deploy lifecycle guide.
Update an existing deployment
To change something about a running cluster (scale a node group, add a gpu group, change instance types, restrict network access), edit your config and re-run the deploy commands as described in Update a cluster.
Changing location or project_name triggers destructive resource recreation. Treat these as one-way decisions.
Destroy
Run the destroy commands as described in Destroy in the deploy lifecycle guide.
nic destroy removes the k3s cluster (all servers), the Hetzner load balancer, and automatically cleans up orphaned Longhorn/CSI block volumes and any load balancers left behind by in-cluster controllers.
If you set persist_data: true in your config, CSI volumes labelled persist=true are skipped during destroy and will continue to bill. Remove them manually from the Hetzner Cloud Console when you no longer need them.
Always confirm in the Hetzner Cloud Console that no orphan servers, volumes, or load balancers remain after destroy.