Skip to content

Repository files navigation

terraform-hcloud-rancher

CodeRabbit Pull Request Reviews Lint: fmt Lint: validate Lint: tflint

SAST: Checkov SAST: KICS SAST: tfsec

Test: variables Test: guardrails

Integration: plan E2E: apply

OpenTofu hcloud rancher2 random RKE2

⚠️ Experimental (Beta) — This is an unofficial community implementation, under active development and not production-ready. APIs, variables, and behavior may change without notice. Use at your own risk. No stability guarantees are provided until v1.0.0.

An OpenTofu/Terraform module that deploys a Rancher management cluster on Hetzner Cloud with built-in Hetzner Node Driver for downstream cluster provisioning via the Rancher UI.

Ecosystem

This module is part of the RKE2-on-Hetzner ecosystem — a set of interconnected projects that together provide a complete Kubernetes management platform on Hetzner Cloud.

Repository Role in Ecosystem
terraform-hcloud-rke2-core L3 infrastructure primitive — servers, network, readiness
terraform-hcloud-rancher (this repo) Management cluster — Rancher + Node Driver on RKE2
rancher-hetzner-cluster-templates Downstream cluster provisioning via Rancher UI
rancher-hcloud-image-controller OSS image controller — watches HetznerConfig, resolves golden:*, triggers build Jobs (ADR-012)

Golden-image build backend: pending selection. The previous Packer-based image builder was dropped (non-free license + poor Hetzner Cloud compatibility); an open-source replacement has not yet been selected. The golden-image delivery concept continues via the OSS image controller (ADR-012).

rke2-core (L3 infra) → rancher (L3+L4 management) → cluster-templates (downstream via UI)
                                                    ↑
                                  image controller (golden:* → build backend pending)

Features

  • Single tofu apply — provisions RKE2 cluster, installs cert-manager, Rancher, bootstraps admin, installs Hetzner Node Driver
  • True Zero-SSH — no SSH keys, no port 22, no sshd (inherited from terraform-hcloud-rke2-core, ADR-002)
  • sslip.io by default — auto-generates hostname from ingress LB IP, zero DNS setup needed
  • BYO DNS — pass rancher_hostname with any FQDN (Route53, Cloudflare, etc.) for production
  • BYO Ingress LB — create or bring your own load balancer (for_each gating pattern)
  • Hetzner Node Driverzsys-studio/rancher-hetzner-cluster-provider installed via cloud-init
  • TLS flexibility — self-signed (Rancher CA), Let's Encrypt, or user-provided certificate
  • Dual Load Balancer — control-plane LB (K8s API) + ingress LB (Rancher UI)
  • CIS hardening — optional RKE2 CIS profile via enable_cis with automatic PSA exemptions for Rancher
  • 2 providers onlyhcloud + rancher2 (all L4 via cloud-init manifests)

Requirements

Tool Version Purpose
OpenTofu >= 1.8.0 Infrastructure as Code
Hetzner Cloud API token Cloud provider

Quick Start

module "rancher" {
  source = "git::https://github.com/mbilan1/terraform-hcloud-rancher.git?ref=v0.1.0"

  hcloud_api_token = var.hcloud_api_token
  admin_password   = var.admin_password

  # rancher_hostname is optional — defaults to sslip.io auto-hostname
  # For production, set a real FQDN:
  # rancher_hostname = "rancher.example.com"
}

See examples/minimal/ for a complete working example.

DNS Configuration

By default, the module auto-generates a sslip.io hostname from the ingress LB IP — no DNS setup is required.

For production, bring your own DNS (Route53, Cloudflare, or any provider):

  1. Deploy with default sslip.io to obtain ingress_lb_ipv4 output
  2. Create an A record in your DNS provider: rancher.example.com → <ingress_lb_ipv4>
  3. Re-apply with the FQDN:
module "rancher" {
  source = "git::https://github.com/mbilan1/terraform-hcloud-rancher.git?ref=v0.1.0"

  hcloud_api_token  = var.hcloud_api_token
  rancher_hostname  = "rancher.example.com"  # Your R53/Cloudflare managed FQDN
  admin_password    = var.admin_password
  tls_source        = "letsEncrypt"
  letsencrypt_email = "ops@example.com"
}

Route53 example: Create an aws_route53_record alongside this module, pointing at the ingress_lb_ipv4 output. See the architecture docs for details.

Architecture

See docs/ARCHITECTURE.md for the full design document including:

  • Module architecture (L3 infrastructure + L4 Kubernetes management)
  • Infrastructure topology (dual LB design)
  • Deployment flow (two-phase apply)
  • Downstream cluster provisioning via Rancher UI
  • Security model
  • Compromise log

Module Structure

terraform-hcloud-rancher/
├── main.tf              # Root facade — BYO LB + cloud-init manifests + module calls
├── variables.tf         # All user-facing input variables
├── outputs.tf           # Module outputs
├── providers.tf         # Provider configurations (hcloud + rancher2)
├── versions.tf          # Provider version constraints
├── guardrails.tf        # Preflight check {} blocks
├── moved.tf             # State migration (singleton → for_each)
├── modules/
│   ├── rke2-cluster/    # L3: Hetzner infrastructure via terraform-hcloud-rke2-core
│   └── rancher/         # L4: Rancher admin bootstrap only (rancher2_bootstrap)
├── examples/
│   ├── minimal/         # Minimal working deployment (sslip.io, self-signed TLS)
│   └── complete/        # HA 3-node with BYO firewall, Let's Encrypt, Packer image
├── tests/               # OpenTofu unit tests (tofu test)
└── docs/
    └── ARCHITECTURE.md  # Full design documentation

Providers

Provider Source Version Purpose
hcloud hetznercloud/hcloud 1.60.1 Hetzner Cloud resources
rancher2 rancher/rancher2 13.1.4 Rancher bootstrap

Note: cert-manager, Rancher, NodeDriver, and UIPlugin are deployed via RKE2 cloud-init manifests (HelmChart CRDs). No helm, kubernetes, or kubectl providers needed.

Requirements

Name Version
terraform >= 1.8.0
hcloud = 1.60.1
rancher2 = 13.1.4
random = 3.8.1

Providers

Name Version
hcloud 1.60.1
random 3.8.1

Resources

Name Type
hcloud_load_balancer.ingress resource
hcloud_load_balancer_network.ingress resource
hcloud_load_balancer_service.http resource
hcloud_load_balancer_service.https resource
hcloud_load_balancer_target.ingress resource
random_password.admin resource

Inputs

Name Description Type Default Required
hcloud_api_token Hetzner Cloud API token for the management project (read/write access required) string n/a yes
admin_password Initial password for the Rancher 'admin' user. Leave empty to auto-generate a secure random password (output as rancher_admin_password). string "" no
cert_manager_version cert-manager Helm chart version to install. string "1.17.2" no
cluster_name Identifier prefix for all provisioned resources (servers, LBs, network). Must be lowercase alphanumeric, max 20 characters. string "rancher" no
control_plane_server_type Hetzner Cloud server type for management cluster nodes. Minimum cx43 (8 vCPU, 16 GB) for Rancher. string "cx43" no
create_ingress_lb Create a Hetzner ingress load balancer for Rancher UI (ports 80/443). Set to false when using a pre-existing or external load balancer. bool true no
enable_cis Enable CIS hardening for the management cluster. Activates RKE2 CIS profile, creates prerequisites (etcd user, kernel params), and exempts cattle-system from PodSecurity restricted policy. Works with both stock ubuntu-24.04 and Packer golden images. bool false no
existing_ingress_lb_ipv4 IPv4 address of an existing ingress load balancer. Only used when create_ingress_lb = false. If set, auto-generates hostname from this IP (unless rancher_hostname is provided). string "" no
firewall_ids List of Hetzner firewall IDs to attach to all management cluster nodes. BYO: create firewalls externally and pass their IDs. list(number) [] no
hcloud_image OS image for management cluster nodes. Use 'ubuntu-24.04' (default) or a Hetzner snapshot ID from a Packer baked image. string "ubuntu-24.04" no
hcloud_network_cidr IPv4 address range for the Hetzner private network in CIDR notation. string "10.0.0.0/16" no
hcloud_network_zone Hetzner network zone encompassing all node locations. string "eu-central" no
hetzner_driver_version Version of zsys-studio/rancher-hetzner-cluster-provider to install as Rancher Node Driver. string "0.9.0" no
install_hetzner_driver Install zsys-studio Hetzner Node Driver for downstream cluster provisioning via Rancher UI. Set to false if the driver is managed externally. bool true no
letsencrypt_email Email address for Let's Encrypt certificate registration. Required when tls_source = 'letsEncrypt', ignored otherwise. string "" no
management_node_count Number of control-plane nodes for the management cluster. Use 1 for dev/test, 3 for HA production. number 1 no
node_location Primary Hetzner datacenter location for management cluster nodes (e.g. 'hel1', 'nbg1', 'fsn1'). string "hel1" no
rancher_hostname FQDN for the Rancher UI (e.g. 'rancher.example.com'). Leave empty to auto-generate from ingress LB IP via sslip.io. string "" no
rancher_version Rancher Helm chart version to install (e.g. '2.13.3'). Must be compatible with the Kubernetes version. string "2.13.3" no
rke2_config Additional RKE2 config.yaml content appended to every management cluster node. string "etcd-snapshot-schedule-cron: \"0 */6 * * *\"\netcd-snapshot-retention: 10\n" no
rke2_version RKE2 release tag to deploy (e.g. 'v1.34.4+rke2r1'). Leave empty for stable channel. string "v1.34.4+rke2r1" no
ssh_key_ids List of Hetzner SSH key IDs to install on management cluster nodes. Empty by default (Zero-SSH). list(number) [] no
subnet_address Subnet allocation for cluster nodes within the private network. string "10.0.1.0/24" no
tls_source TLS certificate source for Rancher. 'rancher' = self-signed CA generated by Rancher, 'letsEncrypt' = Let's Encrypt via cert-manager ACME, 'secret' = user-provided TLS secret. string "rancher" no

Outputs

Name Description
ingress_lb_ipv4 IPv4 address of the ingress load balancer (Rancher UI). Point DNS A record here.
initial_master_ipv4 Public IPv4 of the initial master (control-plane node that bootstrapped the cluster)
network_id Hetzner Cloud private network ID (for cluster template pre-fill — ADR-005)
rancher_admin_password Rancher admin password (auto-generated if not provided). Use to log in at rancher_url.
rancher_admin_token Rancher admin API token for initial configuration. Treat as a secret.
rancher_hostname Effective Rancher hostname (auto-generated from LB IP if not provided)
rancher_url Rancher UI URL (HTTPS)

License

MIT — Copyright (c) 2026 Maksym Bilan

Releases

Packages

Contributors

Languages