Skip to content

Latest commit

 

History

History
460 lines (449 loc) · 107 KB

File metadata and controls

460 lines (449 loc) · 107 KB

Requirements

Name Version
terraform >= 1.10.1
assert >= 0.16.0
cloudinit >= 2.3.7
hcloud >= 1.62.0
helm >= 3.1.1
http >= 3.5.0
kubernetes >= 3.1.0
local >= 2.5.2
random >= 3.8.1
semvers >= 0.7.1
ssh 2.7.0

Providers

Name Version
cloudinit >= 2.3.7
hcloud >= 1.62.0
http >= 3.5.0
local >= 2.5.2
random >= 3.8.1
ssh 2.7.0
terraform n/a

Modules

Name Source Version
agents ./modules/host n/a
control_planes ./modules/host n/a
user_kustomizations ./modules/user_kustomizations n/a
values_merger_cert_manager ./modules/values_merger n/a
values_merger_cilium ./modules/values_merger n/a
values_merger_csi_driver_smb ./modules/values_merger n/a
values_merger_haproxy ./modules/values_merger n/a
values_merger_hetzner_ccm ./modules/values_merger n/a
values_merger_hetzner_csi ./modules/values_merger n/a
values_merger_longhorn ./modules/values_merger n/a
values_merger_nginx ./modules/values_merger n/a
values_merger_rancher ./modules/values_merger n/a
values_merger_traefik ./modules/values_merger n/a

Resources

Name Type
hcloud_firewall.k3s resource
hcloud_floating_ip.agents resource
hcloud_floating_ip.control_planes resource
hcloud_floating_ip_assignment.agents resource
hcloud_floating_ip_assignment.control_planes resource
hcloud_load_balancer.cluster resource
hcloud_load_balancer.control_plane resource
hcloud_load_balancer_network.cluster resource
hcloud_load_balancer_network.control_plane resource
hcloud_load_balancer_service.control_plane resource
hcloud_load_balancer_service.control_plane_rke2_supervisor resource
hcloud_load_balancer_target.cluster resource
hcloud_load_balancer_target.control_plane resource
hcloud_network.k3s resource
hcloud_network_route.nat_route_public_internet resource
hcloud_network_subnet.agent resource
hcloud_network_subnet.control_plane resource
hcloud_network_subnet.nat_router resource
hcloud_network_subnet.vswitch_subnet resource
hcloud_placement_group.agent resource
hcloud_placement_group.agent_named resource
hcloud_placement_group.control_plane resource
hcloud_placement_group.control_plane_named resource
hcloud_primary_ip.agents_ipv4 resource
hcloud_primary_ip.agents_ipv6 resource
hcloud_primary_ip.control_planes_ipv4 resource
hcloud_primary_ip.control_planes_ipv6 resource
hcloud_primary_ip.nat_router_primary_ipv4 resource
hcloud_primary_ip.nat_router_primary_ipv6 resource
hcloud_rdns.agents resource
hcloud_rdns.control_plane_lb_ipv4 resource
hcloud_rdns.nat_router_primary_ipv4 resource
hcloud_rdns.nat_router_primary_ipv6 resource
hcloud_server.nat_router resource
hcloud_ssh_key.k3s resource
hcloud_volume.attached_agent_volume resource
hcloud_volume.attached_control_plane_volume resource
hcloud_volume.longhorn_volume resource
local_file.cert_manager_values resource
local_file.cilium_values resource
local_file.csi_driver_smb_values resource
local_file.haproxy_values resource
local_file.hetzner_ccm_values resource
local_file.longhorn_values resource
local_file.nginx_values resource
local_file.traefik_values resource
local_sensitive_file.kubeconfig resource
local_sensitive_file.kustomization_backup resource
random_password.k3s_token resource
random_password.nat_router_vip_auth_pass resource
random_password.rancher_bootstrap resource
random_password.secrets_encryption_key resource
random_string.nat_router resource
ssh_sensitive_resource.kubeconfig resource
terraform_data.agent_config resource
terraform_data.agent_firewall_validation_contract resource
terraform_data.agent_os_update_services resource
terraform_data.agents resource
terraform_data.agents_replacement_trigger resource
terraform_data.audit_policy resource
terraform_data.authentication_config resource
terraform_data.autoscaled_nodes_kubelet_config resource
terraform_data.autoscaled_nodes_registries resource
terraform_data.configure_attached_agent_volume resource
terraform_data.configure_attached_control_plane_volume resource
terraform_data.configure_autoscaler resource
terraform_data.configure_control_plane_floating_ip resource
terraform_data.configure_floating_ip resource
terraform_data.configure_longhorn_volume resource
terraform_data.control_plane_config resource
terraform_data.control_plane_config_rke2 resource
terraform_data.control_plane_os_update_services resource
terraform_data.control_plane_setup_rke2 resource
terraform_data.control_planes resource
terraform_data.control_planes_rke2 resource
terraform_data.extra_robot_nodes resource
terraform_data.first_control_plane resource
terraform_data.first_control_plane_rke2 resource
terraform_data.helm_values_yaml_contract resource
terraform_data.ingress_load_balancer_destroy_cleanup resource
terraform_data.kube_system_secrets resource
terraform_data.kustomization resource
terraform_data.nat_router_await_cloud_init resource
terraform_data.nat_router_config resource
terraform_data.nat_router_connection_contract resource
terraform_data.nat_router_extra_runcmd resource
terraform_data.nat_router_fail2ban resource
terraform_data.post_install_readiness resource
terraform_data.rke2_ingress_load_balancer_destroy_cleanup resource
terraform_data.rke2_kustomization resource
terraform_data.rke2_post_install_readiness resource
terraform_data.tailscale_agents resource
terraform_data.tailscale_control_planes resource
terraform_data.validation_contract resource
cloudinit_config.autoscaler_config data source
cloudinit_config.autoscaler_config_rke2 data source
cloudinit_config.nat_router_config data source
hcloud_floating_ip.agents_existing data source
hcloud_floating_ip.control_planes_existing data source
hcloud_image.leapmicro_arm_snapshot data source
hcloud_image.leapmicro_x86_snapshot data source
hcloud_images.microos_arm_snapshots data source
hcloud_images.microos_x86_snapshots data source
hcloud_network.additional_nodepool_networks data source
hcloud_network.k3s data source
hcloud_server_types.all data source
hcloud_servers.autoscaled_nodes data source
hcloud_servers.existing_agent_nodes data source
hcloud_servers.existing_control_plane_nodes data source
hcloud_ssh_keys.keys_by_selector data source
http_http.calico_release data source
http_http.gateway_api_standard_crds data source
http_http.hetzner_ccm_release data source
http_http.hetzner_csi_release data source
http_http.kured_manifest data source
http_http.kured_release data source
http_http.my_ipv4 data source
http_http.system_upgrade_controller_crd data source
http_http.system_upgrade_controller_manifest data source

Inputs

Name Description Type Default Required
additional_kubernetes_install_environment Additional environment variables for the k3s binary. Values are written to /etc/environment and must not contain double quotes, backslashes, newlines, dollar signs, or backticks. See for example https://docs.k3s.io/advanced#configuring-an-http-proxy . map(any) {} no
additional_tls_sans Additional TLS SANs to allow connection to control-plane through it. list(string) [] no
address_for_connectivity_test The address to test for external connectivity before proceeding with the installation. Defaults to Google's public DNS. string "8.8.8.8" no
agent_exec_args Agents nodes are started with k3s agent {agent_exec_args}. Values are embedded in a single-quoted shell context, so single quotes and newlines are not allowed. Use this to add kubelet-arg for example. string "" no
agent_kubelet_args Kubelet args for agent nodes. list(string) [] no
agent_nodepools Agent nodepools. Optional annotations are Kubernetes Node annotations applied once by a node-local systemd oneshot when each node joins; later map changes affect only newly created or replaced nodes and do not remove annotations from existing Nodes. Per-node annotations merge with and override nodepool annotations.
list(object({
name = string
server_type = string
location = string
backups = optional(bool)
floating_ip = optional(bool)
floating_ip_type = optional(string, "ipv4")
floating_ip_id = optional(number, null)
floating_ip_rdns = optional(string, null)
labels = list(string)
annotations = optional(map(string), {})
hcloud_labels = optional(map(string), {})
extra_firewall_ids = optional(list(number), [])
taints = list(string)
longhorn_volume_size = optional(number)
longhorn_mount_path = optional(string, "/var/longhorn")
delete_protection = optional(bool, false)
append_random_suffix = optional(bool, true)
swap_size = optional(string, "")
zram_size = optional(string, "")
kubelet_args = optional(list(string), ["kube-reserved=cpu=50m,memory=300Mi,ephemeral-storage=1Gi", "system-reserved=cpu=250m,memory=300Mi"])
selinux = optional(bool, true)
placement_group_index = optional(number, 0)
placement_group = optional(string, null)
subnet_ip_range = optional(string, null)
os = optional(string)
os_snapshot_id = optional(string, null)
count = optional(number, null)
enable_public_ipv4 = optional(bool, true)
enable_public_ipv6 = optional(bool, true)
primary_ipv4_id = optional(number, null)
primary_ipv6_id = optional(number, null)
network_id = optional(number, null)
network_scope = optional(string, null)
keep_disk = optional(bool)
join_endpoint_type = optional(string, "private")
extra_write_files = optional(list(any), [])
extra_runcmd = optional(list(any), [])
attached_volumes = optional(list(object({
size = number
mount_path = string
filesystem = optional(string, "ext4")
automount = optional(bool, true)
name = optional(string, null)
labels = optional(map(string), {})
delete_protection = optional(bool, null)
})), [])
nodes = optional(map(object({
server_type = optional(string)
location = optional(string)
backups = optional(bool)
floating_ip = optional(bool)
floating_ip_type = optional(string, null)
floating_ip_id = optional(number, null)
floating_ip_rdns = optional(string, null)
labels = optional(list(string))
annotations = optional(map(string), {})
hcloud_labels = optional(map(string), {})
extra_firewall_ids = optional(list(number), [])
taints = optional(list(string))
longhorn_volume_size = optional(number)
longhorn_mount_path = optional(string, null)
append_random_suffix = optional(bool)
swap_size = optional(string, "")
zram_size = optional(string, "")
kubelet_args = optional(list(string), ["kube-reserved=cpu=50m,memory=300Mi,ephemeral-storage=1Gi", "system-reserved=cpu=250m,memory=300Mi"])
selinux = optional(bool, true)
placement_group_index = optional(number, null)
placement_group = optional(string, null)
append_index_to_node_name = optional(bool, true)
os = optional(string)
os_snapshot_id = optional(string, null)
enable_public_ipv4 = optional(bool)
enable_public_ipv6 = optional(bool)
primary_ipv4_id = optional(number, null)
primary_ipv6_id = optional(number, null)
network_id = optional(number)
network_scope = optional(string, null)
keep_disk = optional(bool)
join_endpoint_type = optional(string, null)
extra_write_files = optional(list(any), [])
extra_runcmd = optional(list(any), [])
attached_volumes = optional(list(object({
size = number
mount_path = string
filesystem = optional(string, "ext4")
automount = optional(bool, true)
name = optional(string, null)
labels = optional(map(string), {})
delete_protection = optional(bool, null)
})), [])
})))
}))
[] no
agent_nodes_custom_config Additional configuration for agent nodes and autoscaler nodes that will be added to the selected Kubernetes distribution's config.yaml. E.g. to allow kube-proxy monitoring. any {} no
allow_inbound_icmp Allow inbound ICMP ping. bool false no
allow_scheduling_on_control_plane Whether to allow non-control-plane workloads to run on the control-plane nodes. bool false no
audit_log_max_age Maximum number of days to retain audit log files number 30 no
audit_log_max_backups Maximum number of audit log files to retain number 10 no
audit_log_max_size Maximum size in megabytes of the audit log file before rotation number 100 no
audit_log_path Path where audit logs will be stored on control plane nodes string "/var/log/k3s-audit/audit.log" no
audit_policy_config Kubernetes distribution audit-policy.yaml contents. Used to configure Kubernetes audit logging. string "" no
authentication_config Strucutred authentication configuration. This can be used to define external authentication providers. string "" no
automatically_upgrade_kubernetes Whether to automatically upgrade Kubernetes based on the selected channel. This controls the upgrade node label and upgrade activity; it does not control deployment of the system-upgrade-controller. If enable_system_upgrade_controller is false while this remains true, nodes can keep harmless inert upgrade labels because no controller/plans act on them. bool true no
automatically_upgrade_os Whether to enable or disable automatic OS updates through the host transactional-update timer. Defaults to true. Should be disabled for single-node clusters. This does not control deployment of kured. WARNING: if enable_kured is false while this remains true, updates can keep running but there is no module-managed reboot orchestration. bool true no
autoscaler_enable_public_ipv4 Enable public IPv4 on nodes created by the Cluster Autoscaler. bool true no
autoscaler_enable_public_ipv6 Enable public IPv6 on nodes created by the Cluster Autoscaler. bool true no
autoscaler_kubelet_args Kubelet args for autoscaler nodes. list(string) [] no
autoscaler_nodepools Cluster autoscaler nodepools. Optional annotations are Kubernetes Node annotations applied once by autoscaler node cloud-init when each node joins; later map changes affect only newly created or replaced autoscaler nodes and do not remove annotations from existing Nodes.
list(object({
name = string
server_type = string
location = string
min_nodes = number
max_nodes = number
labels = optional(map(string), {})
annotations = optional(map(string), {})
server_labels = optional(map(string), {})
kubelet_args = optional(list(string), ["kube-reserved=cpu=50m,memory=300Mi,ephemeral-storage=1Gi", "system-reserved=cpu=250m,memory=300Mi"])
os = optional(string)
network_id = optional(number, null)
network_scope = optional(string, null)
subnet_ip_range = optional(string, null)
join_endpoint_type = optional(string, null)
taints = optional(list(object({
key = string
value = string
effect = string
})), [])
swap_size = optional(string, "")
zram_size = optional(string, "")
}))
[] no
base_domain Base domain of the cluster, used for reverse dns. string "" no
calico_values Replacement strategic-merge patch for the upstream Calico manifest installed by k3s. This input is not consumed by RKE2, which uses its bundled Calico chart. string "" no
calico_version Version of Calico. Unset uses the reviewed module default; set a concrete release version to pin; set "latest" to resolve the upstream GitHub latest release at plan time. See https://github.com/projectcalico/calico/releases for available versions. string null no
cert_manager_helmchart_bootstrap Whether the HelmChart cert_manager shall be run on control-plane nodes. bool false no
cert_manager_merge_values Additional Helm values to merge with defaults (or cert_manager_values if set). User values take precedence. Requires valid YAML format. string "" no
cert_manager_values Additional helm values file to pass to Cert-Manager as 'valuesContent' at the HelmChart. Defaults are set in locals.tf. For cert-manager versions prior to v1.15.0, you need to set 'installCRDs: true'. string "" no
cert_manager_version Version of the cert-manager Helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart. string null no
cilium_egress_gateway_enabled Enables egress gateway to redirect and SNAT the traffic that leaves the cluster. bool false no
cilium_egress_gateway_ha_enabled Deploys a lightweight controller that keeps CiliumEgressGatewayPolicy node selectors pointed at a currently Ready egress node. bool false no
cilium_gateway_api_enabled Enable Cilium's Gateway API controller and install the standard Gateway API CRDs. Requires Cilium with kube-proxy replacement. bool false no
cilium_hubble_enabled Enables Hubble Observability to collect and visualize network traffic. bool false no
cilium_hubble_metrics_enabled Configures the list of Hubble metrics to collect list(string) [] no
cilium_ipv4_native_routing_cidr Used when Cilium is configured in native routing mode. The CNI assumes that the underlying network stack will forward packets to this destination without the need to apply SNAT. Default: value of "cluster_ipv4_cidr" string null no
cilium_load_balancer_acceleration_mode Set Cilium loadBalancer.acceleration. Supported values are "disabled", "native" and "best-effort". string "best-effort" no
cilium_merge_values Additional Helm values to merge with defaults (or cilium_values if set). User values take precedence. Requires valid YAML format. string "" no
cilium_routing_mode Set native-routing mode ("native") or tunneling mode ("tunnel"). string "tunnel" no
cilium_values Additional helm values file to pass to Cilium as 'valuesContent' at the HelmChart. string "" no
cilium_version Version of Cilium. See https://github.com/cilium/cilium/releases for the available versions. string "1.19.3" no
cluster_autoscaler_extra_args Extra arguments for the Cluster Autoscaler deployment. list(string) [] no
cluster_autoscaler_image Image of Kubernetes Cluster Autoscaler for Hetzner Cloud to be used. string "registry.k8s.io/autoscaling/cluster-autoscaler" no
cluster_autoscaler_log_level Verbosity level of the logs for cluster-autoscaler number 4 no
cluster_autoscaler_log_to_stderr Determines whether to log to stderr or not bool true no
cluster_autoscaler_metrics_firewall_source Optional source CIDRs allowed to scrape cluster-autoscaler metrics through NodePort 30085 (maps to pod port 8085). list(string) [] no
cluster_autoscaler_replicas Number of replicas for the cluster autoscaler deployment. Multiple replicas use leader election for HA. number 1 no
cluster_autoscaler_resource_limits Should cluster autoscaler enable default resource requests and limits. Default values are requests: 10m & 64Mi and limits: 100m & 300Mi. bool true no
cluster_autoscaler_resource_values Requests and limits for Cluster Autoscaler.
object({
requests = object({
cpu = string
memory = string
})
limits = object({
cpu = string
memory = string
})
})
{
"limits": {
"cpu": "100m",
"memory": "300Mi"
},
"requests": {
"cpu": "10m",
"memory": "64Mi"
}
}
no
cluster_autoscaler_server_creation_timeout Timeout (in minutes) until which a newly created server/node has to become available before giving up and destroying it. number 15 no
cluster_autoscaler_stderr_threshold Severity level above which logs are sent to stderr instead of stdout string "INFO" no
cluster_autoscaler_tolerations Additional tolerations to append to the cluster-autoscaler deployment.
list(object({
key = optional(string)
operator = optional(string)
value = optional(string)
effect = optional(string)
tolerationSeconds = optional(number)
}))
[] no
cluster_autoscaler_version Version of Kubernetes Cluster Autoscaler for Hetzner Cloud. Should be aligned with Kubernetes version. Available versions for the official image can be found at https://explore.ggcr.dev/?repo=registry.k8s.io%2Fautoscaling%2Fcluster-autoscaler. string "v1.33.3" no
cluster_dns_ipv4 Internal Service IPv4 address of core-dns. string null no
cluster_ipv4_cidr Internal Pod CIDR, used for the controller and currently for calico/cilium. string "10.42.0.0/16" no
cluster_ipv6_cidr Internal Pod IPv6 CIDR. Set together with service_ipv6_cidr to enable dual-stack or IPv6-only cluster networking. string null no
cluster_name Name of the cluster. string "k3s" no
cluster_token Cluster join token (must match when restoring a cluster). string null no
cni_plugin CNI plugin for k3s. string "flannel" no
control_plane_endpoint Optional external control plane endpoint URL (e.g. https://myapi.domain.com:6443). Used as the k3s 'server' value for agents and secondary control planes. If kubernetes_api_port is overridden, use the same port in this URL. string null no
control_plane_exec_args The control plane is started with k3s server {control_plane_exec_args}. Values are embedded in a single-quoted shell context, so single quotes and newlines are not allowed. Use this to add kube-apiserver-arg for example. string "" no
control_plane_kubelet_args Kubelet args for control plane nodes. list(string) [] no
control_plane_load_balancer_enable_public_network Enable the public interface for the control plane load balancer. Defaults to true. When disabled with nat_router enabled, the NAT router automatically forwards kubernetes_api_port to the private control plane load balancer. bool true no
control_plane_load_balancer_type The type of load balancer to use for the control plane load balancer. Defaults to lb11, which is the cheapest one. string "lb11" no
control_plane_nodepools Control plane nodepools. Optional annotations are Kubernetes Node annotations applied once by a node-local systemd oneshot when each node joins; later map changes affect only newly created or replaced nodes and do not remove annotations from existing Nodes. Per-node annotations merge with and override nodepool annotations.
list(object({
name = string
server_type = string
location = string
backups = optional(bool)
floating_ip = optional(bool, false)
floating_ip_id = optional(number, null)
labels = list(string)
annotations = optional(map(string), {})
hcloud_labels = optional(map(string), {})
taints = list(string)
count = optional(number, null)
append_random_suffix = optional(bool, true)
swap_size = optional(string, "")
zram_size = optional(string, "")
kubelet_args = optional(list(string), ["kube-reserved=cpu=250m,memory=1500Mi,ephemeral-storage=1Gi", "system-reserved=cpu=250m,memory=300Mi"])
selinux = optional(bool, true)
placement_group_index = optional(number, 0)
placement_group = optional(string, null)
os = optional(string)
os_snapshot_id = optional(string, null)
enable_public_ipv4 = optional(bool, true)
enable_public_ipv6 = optional(bool, true)
primary_ipv4_id = optional(number, null)
primary_ipv6_id = optional(number, null)
keep_disk = optional(bool)
join_endpoint_type = optional(string, "private")
extra_write_files = optional(list(any), [])
extra_runcmd = optional(list(any), [])
attached_volumes = optional(list(object({
size = number
mount_path = string
filesystem = optional(string, "ext4")
automount = optional(bool, true)
name = optional(string, null)
labels = optional(map(string), {})
delete_protection = optional(bool, null)
})), [])
nodes = optional(map(object({
server_type = optional(string)
location = optional(string)
backups = optional(bool)
floating_ip = optional(bool)
floating_ip_id = optional(number, null)
labels = optional(list(string))
annotations = optional(map(string), {})
hcloud_labels = optional(map(string), {})
taints = optional(list(string))
append_random_suffix = optional(bool)
swap_size = optional(string, "")
zram_size = optional(string, "")
kubelet_args = optional(list(string), ["kube-reserved=cpu=250m,memory=1500Mi,ephemeral-storage=1Gi", "system-reserved=cpu=250m,memory=300Mi"])
selinux = optional(bool, true)
placement_group_index = optional(number, null)
placement_group = optional(string, null)
os = optional(string)
os_snapshot_id = optional(string, null)
enable_public_ipv4 = optional(bool)
enable_public_ipv6 = optional(bool)
primary_ipv4_id = optional(number, null)
primary_ipv6_id = optional(number, null)
keep_disk = optional(bool)
join_endpoint_type = optional(string, null)
extra_write_files = optional(list(any), [])
extra_runcmd = optional(list(any), [])
attached_volumes = optional(list(object({
size = number
mount_path = string
filesystem = optional(string, "ext4")
automount = optional(bool, true)
name = optional(string, null)
labels = optional(map(string), {})
delete_protection = optional(bool, null)
})), [])
})))
}))
[] no
control_planes_custom_config Additional configuration for control planes that will be added to the selected Kubernetes distribution's config.yaml. E.g. to allow etcd monitoring. any {} no
create_kubeconfig Create the kubeconfig as a local file resource. Should be disabled for automatic runs. bool true no
create_kustomization Create the kustomization backup as a local file resource. Should be disabled for automatic runs. bool true no
csi_driver_smb_helmchart_bootstrap Whether the HelmChart csi_driver_smb shall be run on control-plane nodes. bool false no
csi_driver_smb_merge_values Additional Helm values to merge with defaults (or csi_driver_smb_values if set). User values take precedence. Requires valid YAML format. string "" no
csi_driver_smb_values Additional helm values file to pass to csi-driver-smb as 'valuesContent' at the HelmChart. string "" no
csi_driver_smb_version Version of the csi-driver-smb Helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart available from the upstream repo. string null no
dns_servers IP Addresses to use for the DNS Servers, set to an empty list to use the ones provided by Hetzner. The length is limited to 3 entries, more entries is not supported by kubernetes list(string)
[
"185.12.64.1",
"185.12.64.2",
"2a01:4ff:ff00::add:1"
]
no
embedded_registry_mirror Opt-in k3s/RKE2 embedded distributed registry mirror (Spegel). Adds empty mirror entries for selected registries and enables the embedded-registry server setting.
object({
enabled = optional(bool, false)
registries = optional(list(string), ["docker.io", "registry.k8s.io", "ghcr.io", "quay.io"])
disable_default_endpoint = optional(bool, false)
})
{
"disable_default_endpoint": false,
"enabled": false,
"registries": [
"docker.io",
"registry.k8s.io",
"ghcr.io",
"quay.io"
]
}
no
enable_cert_manager Enable cert manager. bool true no
enable_cni_wireguard_encryption Enable WireGuard encryption in supported CNI integrations. For Flannel this selects wireguard-native unless flannel_backend is set explicitly. bool false no
enable_control_plane_load_balancer Creates a dedicated load balancer for the Kubernetes API (kubernetes_api_port). When enabled, kubectl and other API clients connect through this LB instead of directly to the first control plane node. Recommended for production clusters with multiple control plane nodes for high availability. Note: This is separate from the ingress load balancer for HTTP/HTTPS traffic. bool false no
enable_csi_driver_smb Whether or not to enable csi-driver-smb. bool false no
enable_delete_protection Enable or disable delete protection for resources in Hetzner Cloud.
object({
floating_ip = optional(bool, false)
load_balancer = optional(bool, false)
volume = optional(bool, false)
})
{
"floating_ip": false,
"load_balancer": false,
"volume": false
}
no
enable_experimental_cilium_public_overlay Explicit opt-in gate for the experimental Cilium public-overlay multinetwork preview. This mode is not production-supported until live Cilium datapath validation passes. bool false no
enable_hetzner_csi Enable the Hetzner CSI driver. bool true no
enable_klipper_metal_lb Use klipper load balancer. bool false no
enable_kube_proxy Enable kube-proxy. Set false only with Cilium kube-proxy replacement. bool true no
enable_kured Whether to include kured (the Kubernetes Reboot Daemon) in the module kustomization used to perform safe, HA-aware node reboots after OS updates. Set to false to skip deploying it on new clusters or on the next kustomization re-run, for example when it is managed externally (GitOps/ArgoCD). Disabling this does not prune/remove kured resources already applied to an existing cluster. WARNING: if automatically_upgrade_os is true while this is false, host transactional-update timers remain active but there is no module-managed reboot orchestration. bool true no
enable_load_balancer_monitoring Enable ServiceMonitor and PrometheusRule resources for Hetzner CCM load balancer metrics. Requires Prometheus Operator CRDs. bool false no
enable_local_storage Whether to enable or disable k3s local-storage. Warning: when enabled, there will be two default storage classes: "local-path" and "hcloud-volumes"! bool false no
enable_longhorn Whether or not to enable Longhorn. bool false no
enable_metrics_server Whether to enable or disable k3s metric server. bool true no
enable_network_policy Enable the built-in K3s network policy controller for Flannel. Calico and Cilium force the built-in controller off. bool true no
enable_placement_groups Whether to enable Hetzner spread placement groups. Hetzner spread groups support at most 10 servers per group and 50 placement groups per project; count-based static nodepools without an explicit placement_group are auto-sharded every 10 servers. bool true no
enable_rancher Enable rancher. bool false no
enable_robot_ccm Enables the integration of Hetzner Robot dedicated servers via the Cloud Controller Manager (CCM). If true, robot_user and robot_password must also be provided, otherwise the integration will not be activated. bool false no
enable_secrets_encryption Enable API server EncryptionConfiguration for Kubernetes Secrets at rest. In-place key rotation or disablement is rejected because a single-key replacement can make existing Secrets unreadable; use an explicit staged multi-key Kubernetes rotation procedure. bool false no
enable_selinux Enable SELinux on nodes that also have nodepool-level selinux enabled. bool true no
enable_system_upgrade_controller Whether to include the system-upgrade-controller, its CRDs, and upgrade plans in the module kustomization used for automated Kubernetes upgrades. Set to false to skip deploying it on new clusters or on the next kustomization re-run, for example when it is managed externally (GitOps/ArgoCD). Disabling this does not prune/remove system-upgrade-controller resources already applied to an existing cluster. If automatically_upgrade_kubernetes is true while this is false, nodes can keep harmless inert upgrade labels because no controller/plans act on them. bool true no
enabled_architectures CPU architectures allowed for nodepools and snapshot lookups. Use ["x86"], ["arm"], or ["x86", "arm"]. Hetzner CAX server types are ARM; other Cloud server families are treated as x86. list(string)
[
"x86",
"arm"
]
no
etcd_s3_backup Etcd cluster state backup to S3 storage map(any) {} no
exclude_agents_from_external_load_balancers Add node.kubernetes.io/exclude-from-external-load-balancers=true label to agent nodes. Enable this if you use both the Terraform-managed ingress LB and CCM-managed LoadBalancer services, and want to prevent double-registration of agents to the CCM LBs. Note: This excludes agents from ALL CCM-managed LoadBalancer services, not just ingress. bool false no
existing_network Existing Hetzner Cloud Network to use as the primary kube-hetzner network. If null, the module creates the primary Network. NOTE: make sure network_ipv4_cidr matches the existing Network IP range.
object({
id = number
})
null no
export_values Export for deployment used values.yaml-files as local files. bool false no
expose_routes_to_vswitch Expose primary Network routes to the coupled Robot vSwitch when vswitch_id is set and kube-hetzner manages the primary Network. Existing Networks must enable this outside the module. bool true no
extra_firewall_ids Additional existing Hetzner Firewall IDs to attach to every public control-plane and agent server. The module-managed firewall uses one of Hetzner's five server firewall slots, leaving at most four unique extra IDs across all scopes. list(number) [] no
extra_firewall_rules Additional firewall rules to apply to the cluster. list(any) [] no
extra_network_ids Additional network IDs to attach to every control plane and agent node. list(number) [] no
extra_robot_nodes Optional existing Hetzner Robot nodes to configure as additional k3s agents through the vSwitch subnet.
list(object({
host = string
private_ipv4 = string
vlan_id = number
interface = optional(string, "enp6s0")
mtu = optional(number, 1350)
ssh_user = optional(string, "root")
ssh_port = optional(number, 22)
ssh_private_key = optional(string, null)
routes = optional(list(string), ["10.0.0.0/8"])
labels = optional(list(string), ["instance.hetzner.cloud/provided-by=robot"])
taints = optional(list(string), [])
flannel_iface = optional(string, null)
}))
[] no
firewall_kube_api_source Source networks that have Kube API access to the servers. WARNING: the 'myipv4' placeholder (auto-detected via icanhazip.com) can return an incorrect IP behind VPNs, proxies, CDNs, or CI/CD runners, silently locking you out. We recommend deploying with open access first, then tightening to your known CIDRs after the cluster is up. list(string)
[
"0.0.0.0/0",
"::/0"
]
no
firewall_ssh_source Source networks that have SSH access to the servers. WARNING: the 'myipv4' placeholder (auto-detected via icanhazip.com) can return an incorrect IP behind VPNs, proxies, CDNs, or CI/CD runners, causing provisioning to hang indefinitely. We recommend deploying with open access first, then tightening to your known CIDRs after the cluster is up. list(string)
[
"0.0.0.0/0",
"::/0"
]
no
flannel_backend Override the flannel backend used by k3s. When set, this takes precedence over enable_cni_wireguard_encryption. Valid values: vxlan, host-gw, wireguard-native. See https://docs.k3s.io/networking/basic-network-options for details. Use wireguard-native for Robot nodes with vSwitch to avoid MTU issues. string null no
gateway_api_version Standard Gateway API CRD release tag to fetch from kubernetes-sigs/gateway-api when Cilium Gateway API or Traefik's Kubernetes Gateway provider is enabled. Default empty string keeps the v3 behavior of deriving the CRD bundle from cilium_version; set this to a release tag such as v1.5.1 to pin the Gateway API CRDs independently. string "" no
global_kubelet_args Global kubelet args for all nodes. list(string) [] no
haproxy_additional_proxy_protocol_ips Additional transport-peer CIDRs required to send PROXY protocol to HAProxy. Use verified peer /32 or /128 addresses, not client or CDN ranges; ordinary HTTP/TLS from matching peers will fail. See docs/haproxy-proxy-protocol.md. list(string) [] no
haproxy_merge_values Additional Helm values to merge with defaults (or haproxy_values if set). User values take precedence. Requires valid YAML format. string "" no
haproxy_requests_cpu Setting for HAProxy controller.resources.requests.cpu string "250m" no
haproxy_requests_memory Setting for HAProxy controller.resources.requests.memory string "400Mi" no
haproxy_values Helm values file to pass to haproxy as 'valuesContent' at the HelmChart, overriding the default. string "" no
haproxy_version Version of HAProxy Kubernetes Ingress helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart. string null no
hcloud_ssh_key_id If passed, a key already registered within hetzner is used. Otherwise, a new one will be created by the module. string null no
hcloud_token Hetzner Cloud API Token. string n/a yes
hetzner_ccm_merge_values Additional Helm values to merge with defaults (or hetzner_ccm_values if set). User values take precedence. Requires valid YAML format. string "" no
hetzner_ccm_values Additional helm values file to pass to Hetzner Controller Manager as 'valuesContent' at the HelmChart. string "" no
hetzner_ccm_version Version of Kubernetes Cloud Controller Manager for Hetzner Cloud. Unset uses the reviewed module default; set a concrete version to pin; set "latest" to resolve the upstream GitHub latest release at plan time. See https://github.com/hetznercloud/hcloud-cloud-controller-manager/releases for available versions. string null no
hetzner_csi_merge_values Additional Helm values to merge with defaults (or hetzner_csi_values if set). User values take precedence. Requires valid YAML format. string "" no
hetzner_csi_values Additional helm values file to pass to hetzner csi as 'valuesContent' at the HelmChart. string "" no
hetzner_csi_version Version of Container Storage Interface driver for Hetzner Cloud. Unset uses the reviewed module default; set a concrete version to pin; set "latest" to resolve the upstream GitHub latest release at plan time. See https://github.com/hetznercloud/csi-driver/releases for available versions. string null no
ingress_controller The name of the ingress controller. string "traefik" no
ingress_controller_use_system_namespace Deploy the selected ingress controller into kube-system unless ingress_target_namespace is explicitly set. bool false no
ingress_max_replica_count Number of maximum replicas per ingress controller. Used for ingress HPA. Must be higher than number of replicas. number 10 no
ingress_replica_count Number of replicas per ingress controller. 0 means autodetect based on the number of agent nodes. number 0 no
ingress_target_namespace The namespace to deploy the ingress controller to. Defaults to ingress name. string "" no
k3s_artifact_sha256 Optional independently reviewed SHA-256 digests for an exact k3s_version not included in this module's release manifest. Include each architecture you want independently pinned. Missing architectures preserve existing custom-version behavior by using the exact official release checksum publication. Built-in reviewed versions ignore this override. map(string) {} no
k3s_channel Selects the k3s channel. Initial bootstrap uses the exact channel release reviewed with this module version; System Upgrade Controller plans can continue following the live channel. v1.33 and v1.36 are accepted for explicit minor-line pinning; use k3s_version for an exact release. string "stable" no
k3s_version Allows you to specify the k3s version (Example: v1.29.6+k3s2). Supersedes k3s_channel. See https://github.com/k3s-io/k3s/releases for available versions. string "" no
keep_disk_agent_nodes Whether to keep OS disks of nodes the same size when upgrading an agent node bool false no
keep_disk_control_plane_nodes Whether to keep OS disks of nodes the same size when upgrading a control-plane node bool false no
kube_apiserver_args Additional raw kube-apiserver flags appended to the control-plane config.yaml (kube-apiserver-arg), e.g. ["service-account-issuer=https://...", "service-account-jwks-uri=https://..."] for OIDC workload identity. These entries are appended after module-generated apiserver args such as authentication_config and audit_policy_config; duplicate k3s/rke2 config flag keys are last-wins, so this intentionally allows overriding module defaults as an escape hatch. Applied in-place via the existing config-update script (k3s/rke2 service restart, no control-plane node recreation). Entries are "flag=value" without a leading "--". list(string) [] no
kubeconfig_server_address The hostname used for kubeconfig. string "" no
kubelet_config Kubernetes distribution kubelet-config.yaml contents. Used to configure the kubelet. string "" no
kubernetes_api_port Kubernetes API server port used for k3s control-plane listeners, load balancer listeners, firewall rules, and default join endpoints. RKE2 currently requires the default 6443 API port; RKE2 node registration still uses supervisor port 9345. number 6443 no
kubernetes_config_updates_use_kured_sentinel When true, k3s/rke2 config updates trigger Kured via reboot sentinel instead of immediate service restarts. bool false no
kubernetes_distribution Kubernetes distribution type. Can be either k3s or rke2. string "k3s" no
kured_options n/a map(string) {} no
kured_version Version of Kured. Unset uses the reviewed module default; set a concrete release version to pin; set "latest" to resolve the upstream GitHub latest release at plan time. See https://github.com/kubereboot/kured/releases for available versions. string null no
leapmicro_arm_snapshot_id Leap Micro ARM snapshot ID to be used. If empty, the most recent leapmicro snapshot matching the selected kubernetes_distribution will be used. string "" no
leapmicro_x86_snapshot_id Leap Micro x86 snapshot ID to be used. If empty, the most recent leapmicro snapshot matching the selected kubernetes_distribution will be used. string "" no
load_balancer_algorithm_type Specifies the algorithm type of the load balancer. string "round_robin" no
load_balancer_enable_ipv6 Enable IPv6 for the ingress load balancer. bool true no
load_balancer_enable_public_network Enable the public network of the ingress load balancer. bool true no
load_balancer_health_check_interval Specifies the interval at which a health check is performed. Minimum is 3s. string "15s" no
load_balancer_health_check_retries Specifies the number of times a health check is retried before a target is marked as unhealthy. number 3 no
load_balancer_health_check_timeout Specifies the timeout of a single health check. Must not be greater than the health check interval. Minimum is 1s. string "10s" no
load_balancer_hostname The Hetzner Load Balancer hostname, for either Traefik, HAProxy or Ingress-Nginx. string "" no
load_balancer_location Default load balancer location. string "nbg1" no
load_balancer_type Default load balancer server type. string "lb11" no
longhorn_fstype The longhorn fstype. string "ext4" no
longhorn_helmchart_bootstrap Whether the HelmChart longhorn shall be run on control-plane nodes. bool false no
longhorn_merge_values Helm values to merge with defaults (or longhorn_values if set). User values take precedence. Use for targeted overrides like image tags. Requires valid YAML format. string "" no
longhorn_namespace Namespace for longhorn deployment, defaults to 'longhorn-system' string "longhorn-system" no
longhorn_replica_count Number of replicas per longhorn volume. number 3 no
longhorn_repository By default the official chart which may be incompatible with rancher is used. If you need to fully support rancher switch to https://charts.rancher.io. string "https://charts.longhorn.io" no
longhorn_values Helm values passed as valuesContent to the Longhorn HelmChart. When set, this replaces the module defaults. string "" no
longhorn_version Longhorn Helm chart version. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart. string null no
microos_arm_snapshot_id MicroOS ARM snapshot ID to use. If empty, selects the newest available snapshot matching kubernetes_distribution, then falls back to the newest legacy snapshot without a distro label. string "" no
microos_x86_snapshot_id MicroOS x86 snapshot ID to use. If empty, selects the newest available snapshot matching kubernetes_distribution, then falls back to the newest legacy snapshot without a distro label. string "" no
multinetwork_cilium_mtu Cilium device MTU used by the experimental cilium_public_overlay preview. The default leaves room for Hetzner public networking plus Cilium tunnel and WireGuard overhead. number 1370 no
multinetwork_cilium_peer_ipv4_cidrs IPv4 source CIDRs allowed to reach Cilium public overlay peer ports on every node when the experimental cilium_public_overlay preview is enabled. list(string)
[
"0.0.0.0/0"
]
no
multinetwork_cilium_peer_ipv6_cidrs IPv6 source CIDRs allowed to reach Cilium public overlay peer ports on every node when the experimental cilium_public_overlay preview is enabled with IPv6 or dual-stack transport. list(string)
[
"::/0"
]
no
multinetwork_mode Optional multinetwork topology mode. Use "disabled" for the existing single-private-network behavior. "cilium_public_overlay" is an experimental preview that lets Cilium span multiple Hetzner Networks over public node addresses with WireGuard encryption. string "disabled" no
multinetwork_transport_ip_family Public transport address family for the experimental cilium_public_overlay preview. IPv4 is the conservative default; IPv6 and dualstack require public IPv6 on every node. string "ipv4" no
myipv4_ref Placeholder string that can be used in firewall source/destination IP lists and will be replaced by the apply runner's public IPv4 /32. string "myipv4" no
nat_router Do you want to pipe all egress through a single nat router which is to be constructed? Note: Requires enable_control_plane_load_balancer=true unless node_transport_mode="tailscale" provides the API/kubeconfig path through the tailnet. Automatically forwards kubernetes_api_port to the control plane LB when control_plane_load_balancer_enable_public_network=false. extra_runcmd commands run as root after NAT router cloud-init completes and rerun when the command list changes.
object({
server_type = string
location = string
labels = optional(map(string), {})
enable_sudo = optional(bool, false)
enable_redundancy = optional(bool, false)
standby_location = optional(string, "")
extra_runcmd = optional(list(string), [])
})
null no
nat_router_hcloud_token API Token used by the nat-router to change ip assignment when nat_router.enable_redundancy is true. string "" no
nat_router_subnet_index Subnet index for NAT router. Default 200 is safe for most deployments. Must not conflict with control plane (counting down from 255) or agent pools (counting up from 0). number 200 no
network_ipv4_cidr The main network cidr that all subnets will be created upon. string "10.0.0.0/8" no
network_region Default region for network. string "eu-central" no
network_subnet_mode Subnet allocation mode for the primary private network. Use "per_nodepool" to allocate dedicated subnets per control-plane and agent nodepool. Use "shared" to allocate one shared agent subnet from the start of the CIDR and one shared control-plane subnet from the end. string "per_nodepool" no
nginx_merge_values Additional Helm values to merge with defaults (or nginx_values if set). User values take precedence. Requires valid YAML format. string "" no
nginx_values Additional helm values file to pass to nginx as 'valuesContent' at the HelmChart. string "" no
nginx_version Version of Nginx helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart. See https://github.com/kubernetes/ingress-nginx?tab=readme-ov-file#supported-versions-table for available versions. string null no
node_connection_overrides Optional map of node name => SSH host override. Use this to route Terraform SSH/provisioning through external access or overlay networks managed outside this module (for example ZeroTier, WireGuard, or Cloudflare Tunnel/WARP). For kube-hetzner-managed Tailscale node transport, use node_transport_mode="tailscale". Cloudflare Access/Tunnel is external access only; Cloudflare Mesh/WARP is not a supported v3 node transport. map(string) {} no
node_transport_mode Kubernetes node transport mode. "hetzner_private" keeps the classic Hetzner private Network transport. "tailscale" makes Tailscale the official node transport and secure Tailnet access path for single-network hardening and supported large-cluster multinetwork topologies. string "hetzner_private" no
optional_bastion_host Optional bastion host used to connect to cluster nodes. Useful when using a pre-existing NAT router.
object({
bastion_host = string
bastion_port = number
bastion_user = string
bastion_private_key = string
})
null no
postinstall_exec Additional to execute after the install calls, for example restoring a backup. list(string) [] no
prefer_bundled_bin Whether to use the bundled k3s mount binary instead of the one from the distro's util-linux package. bool false no
preinstall_exec Additional to execute before the install calls, for example fetching and installing certs. list(string) [] no
primary_ip_pool Module-managed Primary IP pool settings. When enabled, kube-hetzner creates and assigns one Primary IP per node for the selected IP families.
object({
enable_ipv4 = optional(bool, false)
enable_ipv6 = optional(bool, false)
auto_delete = optional(bool, false)
})
{} no
rancher_bootstrap_password Rancher bootstrap password. string "" no
rancher_helmchart_bootstrap Whether the HelmChart rancher shall be run on control-plane nodes. bool false no
rancher_hostname The rancher hostname. string "" no
rancher_install_channel The rancher installation channel. string "stable" no
rancher_merge_values Additional Helm values to merge with defaults (or rancher_values if set). User values take precedence. Requires valid YAML format. string "" no
rancher_registration_manifest_url The url of a rancher registration manifest to apply. (see https://rancher.com/docs/rancher/v2.6/en/cluster-provisioning/registered-clusters/). string "" no
rancher_values Additional helm values file to pass to Rancher as 'valuesContent' at the HelmChart. string "" no
rancher_version Version of the Rancher Helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart in rancher_install_channel. string null no
registries_config Kubernetes distribution registries.yaml contents, used to configure private registries and registry mirrors. string " " no
restrict_outbound_traffic Whether or not to restrict the outbound traffic. bool true no
reuse_control_plane_load_balancer Reuse the control plane load balancer for ingress services as well. Requires enable_control_plane_load_balancer=true. bool false no
rke2_artifact_sha256 Optional independently reviewed SHA-256 digests for an exact rke2_version not included in this module's release manifest. Include each architecture you want independently pinned. Missing architectures preserve existing custom-version behavior by using the exact official release checksum publication. Built-in reviewed versions ignore this override. map(string) {} no
rke2_channel Selects the RKE2 channel when rke2_version is empty. Initial bootstrap uses the exact channel release reviewed with this module version; System Upgrade Controller plans can continue following the live channel. v1.36 is accepted for minor-line pinning; explicitly clear the default rke2_version to follow a channel. Use rke2_version for an exact release. string "v1.32" no
rke2_version Allows you to specify the rke2 version (Example: v1.32.5+rke2r1). Supersedes rke2_channel. See https://github.com/rancher/rke2/releases for available versions. string "v1.32.5+rke2r1" no
robot_password Password for the Hetzner Robot webservice string "" no
robot_user User for the Hetzner Robot webservice string "" no
service_ipv4_cidr Internal Service CIDR, used for the controller and currently for calico/cilium. string "10.43.0.0/16" no
service_ipv6_cidr Internal Service IPv6 CIDR. Set together with cluster_ipv6_cidr to enable dual-stack or IPv6-only cluster networking. string null no
ssh_additional_public_keys Additional single-line OpenSSH public keys. Use them to grant other team members root access to your cluster nodes. list(string) [] no
ssh_authorized_keys_exclusive Whether to manage /root/.ssh/authorized_keys exclusively on cluster nodes. The default false preserves unknown out-of-band keys while revoking module-managed keys removed from ssh_public_key or ssh_additional_public_keys. Set true to replace the file with only module-managed keys. bool false no
ssh_hcloud_key_label Additional SSH public Keys by hcloud label. e.g. role=admin string "" no
ssh_max_auth_tries The maximum number of authentication attempts permitted per connection. number 2 no
ssh_port The SSH port configured at node creation and used by Terraform connections. Changing it does not migrate existing node listeners and can interrupt SSH access. See docs/ssh.md#ssh-port-lifecycle before changing it on an existing cluster. number 22 no
ssh_private_key SSH private Key. string n/a yes
ssh_public_key Single-line OpenSSH public key used for node access. string n/a yes
subnet_count The amount of subnets into which the network will be split. Must be a power of 2. number 256 no
system_upgrade_controller_version Version of the System Upgrade Controller for automated Kubernetes upgrades. v0.15.0+ supports the 'window' parameter for scheduling upgrades. See https://github.com/rancher/system-upgrade-controller/releases for available versions. string "v0.18.0" no
system_upgrade_enable_eviction Whether to directly delete pods during Kubernetes system upgrades or evict them. Defaults to true. Disable this on small clusters to avoid system upgrades hanging since pods resisting eviction keep nodes unschedulable forever. NOTE: turning this off introduces potential downtime for services on upgraded nodes. bool true no
system_upgrade_schedule_window Schedule window for automated Kubernetes upgrades managed by system-upgrade-controller v0.15.0+. When set, upgrade jobs will only be created within the specified time window. 'days' accepts lowercase day names (e.g. ["monday","tuesday"]). 'startTime'/'endTime' use HH:MM format. 'timeZone' defaults to UTC.
object({
days = optional(list(string), [])
startTime = optional(string, "")
endTime = optional(string, "")
timeZone = optional(string, "UTC")
})
null no
system_upgrade_use_drain Wether using drain (true, the default), which will deletes and transfers all pods to other nodes before a node is being upgraded, or cordon (false), which just prevents schedulung new pods on the node during upgrade and keeps all pods running bool true no
tailscale_agent_auth_key Optional static-agent-specific Tailscale auth key. Use this when static agents need a different Tailscale key policy than control planes or autoscaler-created nodes. It must be reusable if it is shared by multiple static agents. string null no
tailscale_auth_key Sensitive default Tailscale auth key used when node_transport_mode="tailscale" and tailscale_node_transport.auth.mode="auth_key". Role-specific keys override it. If this key is used by more than one node it must be reusable; single-use keys only register the first node. In cloud_init mode this is rendered into hcloud user_data and, for autoscaler nodes, a Kubernetes Secret. string null no
tailscale_autoscaler_auth_key Optional autoscaler-specific Tailscale auth key. Prefer a reusable, pre-approved, tagged, ephemeral key for autoscaler nodes so deleted machines do not linger in the tailnet. string null no
tailscale_control_plane_auth_key Optional control-plane-specific Tailscale auth key. Use this when static control-plane nodes need a different Tailscale key policy than agents or autoscaler-created nodes. It must be reusable if it is shared by multiple control-plane nodes. string null no
tailscale_node_transport Configuration for node_transport_mode="tailscale". Tailscale is used as secure node transport and Tailnet access. In multinetwork topologies it advertises node-private routes; it is not a CNI and does not manage pod networking by itself.
object({
bootstrap_mode = optional(string, "remote_exec")
version = optional(string, "latest")
magicdns_domain = optional(string, null)
hostname_mode = optional(string, "node_name")

auth = optional(object({
mode = optional(string, "auth_key")
advertise_tags_control_plane = optional(list(string), [])
advertise_tags_agent = optional(list(string), [])
advertise_tags_autoscaler = optional(list(string), [])
oauth_static_nodes_ephemeral = optional(bool, false)
oauth_autoscaler_ephemeral = optional(bool, true)
oauth_preauthorized = optional(bool, true)
}), {})

ssh = optional(object({
use_tailnet_for_terraform = optional(bool, true)
enable_tailscale_ssh = optional(bool, false)
}), {})

routing = optional(object({
advertise_node_private_routes = optional(bool, true)
advertise_additional_routes = optional(list(string), [])
}), {})

kubernetes = optional(object({
cni_mtu = optional(number, 1280)
kubeconfig_endpoint = optional(string, "first_control_plane_tailnet")
}), {})

enable_experimental_cilium = optional(bool, false)
enable_experimental_rke2 = optional(bool, false)
})
{} no
tailscale_oauth_client_secret Sensitive Tailscale OAuth client secret used when node_transport_mode="tailscale" and tailscale_node_transport.auth.mode="oauth_client_secret". The module appends role-specific OAuth auth-key parameters for static and autoscaler nodes. In cloud_init mode this is rendered into hcloud user_data and, for autoscaler nodes, a Kubernetes Secret. string null no
traefik_additional_options Additional options to pass to Traefik as a list of strings. These are the ones that go into the additionalArguments section of the Traefik helm values file. list(string) [] no
traefik_additional_ports Additional ports to pass to Traefik. These are the ones that go into the ports section of the Traefik helm values file.
list(object({
name = string
port = number
exposedPort = number
protocol = optional(string, "TCP")
}))
[] no
traefik_additional_trusted_ips Additional Trusted IPs to pass to Traefik. These are the ones that go into the trustedIPs section of the Traefik helm values file. list(string) [] no
traefik_autoscaling Should traefik enable Horizontal Pod Autoscaler. bool true no
traefik_image_tag Traefik image tag. Useful to use the beta version for new features. Example: v3.0.0-beta5 string "" no
traefik_merge_values Additional Helm values to merge with defaults (or traefik_values if set). User values take precedence. Requires valid YAML format. string "" no
traefik_pod_disruption_budget Should traefik enable pod disruption budget. Default values are maxUnavailable: 33% and minAvailable: 1. bool true no
traefik_provider_kubernetes_gateway_enabled Should traefik enable the kubernetes gateway provider. Default is false. bool false no
traefik_redirect_to_https Should traefik redirect http traffic to https. bool true no
traefik_resource_limits Should traefik enable default resource requests and limits. Default values are requests: 100m & 50Mi and limits: 300m & 150Mi. bool true no
traefik_resource_values Requests and limits for Traefik.
object({
requests = object({
cpu = string
memory = string
})
limits = object({
cpu = string
memory = string
})
})
{
"limits": {
"cpu": "300m",
"memory": "150Mi"
},
"requests": {
"cpu": "100m",
"memory": "50Mi"
}
}
no
traefik_values Additional helm values file to pass to Traefik as 'valuesContent' at the HelmChart. string "" no
traefik_version Version of Traefik helm chart. Unset uses the reviewed module default; set a concrete chart version to pin; set "latest" or legacy "*" to let the Helm controller follow the latest chart. See https://github.com/traefik/traefik-helm-chart/releases for available versions. string null no
use_cluster_name_in_node_name Whether to use the cluster name in the node name. bool true no
use_private_nat_router_bastion Use the NAT router's private IP as the SSH bastion instead of its public IP. Requires the operator to have network-level access to the private network (for example Tailscale, Cloudflare Tunnel, WireGuard VPN, etc). Cloudflare here is an external access path, not kube-hetzner-managed node transport. bool false no
user_kustomizations Map of Kustomization-set entries, where key is the order number. Each non-empty set must point source_folder at templates including a rendered kustomization file; set allow_empty = true only for intentional no-op sets.
map(object({
source_folder = optional(string, "")
kustomize_parameters = optional(map(any), {})
pre_commands = optional(string, "")
post_commands = optional(string, "")
apply_options = optional(list(string), [])
allow_empty = optional(bool, false)
}))
{
"1": {
"allow_empty": true,
"apply_options": [],
"kustomize_parameters": {},
"post_commands": "",
"pre_commands": "",
"source_folder": "extra-manifests"
}
}
no
vswitch_id Hetzner Cloud vSwitch ID. If defined, a subnet will be created in the IP-range defined by vswitch_subnet_index. The vSwitch must exist before this module is called. number null no
vswitch_subnet_index Subnet index (0-255) for vSwitch. Default 201 is safe for most deployments. Must not conflict with control plane (counting down from 255) or agent pools (counting up from 0). number 201 no

Outputs

Name Description
agent_nodes The agent nodes
agents Full agent module map keyed by node identifier.
agents_public_ipv4 The public IPv4 addresses of the agent servers.
agents_public_ipv6 The public IPv6 addresses of the agent servers.
cert_manager_values Helm values.yaml used for cert-manager
cilium_values Helm values.yaml used for Cilium
cluster_name Shared suffix for all resources belonging to this cluster.
cluster_token The cluster token to register new nodes
control_plane_nodes The control plane nodes
control_planes Full control plane module map keyed by node identifier.
control_planes_public_ipv4 The public IPv4 addresses of the controlplane servers.
control_planes_public_ipv6 The public IPv6 addresses of the controlplane servers.
csi_driver_smb_values Helm values.yaml used for SMB CSI driver
domain_assignments Assignments of domains to IPs based on reverse DNS
effective_kubeconfig_endpoint Effective Kubernetes API endpoint written into the generated kubeconfig.
effective_node_join_endpoint Effective default node join endpoint for the selected Kubernetes distribution.
haproxy_values Helm values.yaml used for HAProxy
ingress_public_ipv4 The public IPv4 address of the Hetzner load balancer (with fallback to first control plane node)
ingress_public_ipv6 The public IPv6 address of the Hetzner load balancer (with fallback to first control plane node)
join_script_external Verified helper command for joining and starting non-managed external k3s agents with external-IP and wireguard-native flannel. Replace <PUBLIC_NODE_IP> before running it as root; SELinux hosts must have k3s-selinux installed.
k3s_endpoint A controller endpoint to register new nodes
kubeconfig Kubeconfig file content with external IP address, or internal IP address if only private ips are available
kubeconfig_data Structured kubeconfig data to supply to other providers
kubeconfig_file Kubeconfig file content with external IP address, or internal IP address if only private ips are available
lb_control_plane_ipv4 The public IPv4 address of the Hetzner control plane load balancer
lb_control_plane_ipv6 The public IPv6 address of the Hetzner control plane load balancer
load_balancer_public_ipv4 The public IPv4 address of the Terraform-managed ingress load balancer, if present.
longhorn_values Helm values.yaml used for Longhorn
nat_router_public_ipv4 The address of the nat router, if it exists.
nat_router_public_ipv4_addresses The addresses of all nat routers, if they exist.
nat_router_public_ipv6 The address of the nat router, if it exists.
nat_router_public_ipv6_addresses The addresses of all nat routers, if they exist.
nat_router_ssh_port The non-root user as which you can ssh into the router.
nat_router_username The non-root user as which you can ssh into the router.
network_id The ID of the HCloud network.
nginx_values Helm values.yaml used for nginx-ingress
node_transport_mode Effective Kubernetes node transport mode.
ssh_key_id The ID of the HCloud SSH key.
tailscale_agent_magicdns_hosts Tailnet MagicDNS hostnames for static agent nodes when node_transport_mode is tailscale.
tailscale_control_plane_magicdns_hosts Tailnet MagicDNS hostnames for control-plane nodes when node_transport_mode is tailscale.
traefik_values Helm values.yaml used for Traefik
vswitch_subnet Attributes of the vSwitch subnet.