Skip to content

danylomikula/terraform-hcloud-server

Repository files navigation

Hetzner Cloud Server Terraform Module

Release Pre-Commit License

Terraform module for managing Hetzner Cloud servers with full support for all provider features including private networks, firewalls, placement groups, and advanced configuration options.

Features

  • Multi-server management: Manage multiple servers with a single module invocation.
  • Private networking: Attach servers to Hetzner Cloud private networks with static IPs.
  • Firewall integration: Apply firewalls at server creation time.
  • Placement groups: Control server placement for high availability or performance.
  • Flexible configuration: Support for all hcloud_server resource attributes.
  • Common settings: Apply SSH keys, labels, and firewalls to all servers.
  • Rich outputs: Detailed server information grouped by location, type, and more.

Usage

Basic Single Server

module "server" {
  source  = "danylomikula/server/hcloud"
  version = "~> 1.0"

  servers = {
    web-1 = {
      server_type = "cx23"
      location    = "nbg1"
      image       = "ubuntu-24.04"
      ssh_keys    = [12345]

      labels = {
        role = "webserver"
      }
    }
  }
}

Servers with Private Network

module "network" {
  source  = "danylomikula/network/hcloud"
  version = "~> 1.0"

  create_network = true
  name           = "app-network"
  ip_range       = "10.0.0.0/16"

  subnets = {
    main = {
      type         = "cloud"
      network_zone = "eu-central"
      ip_range     = "10.0.1.0/24"
    }
  }
}

module "servers" {
  source  = "danylomikula/server/hcloud"
  version = "~> 1.0"

  servers = {
    app-01 = {
      server_type = "cx23"
      location    = "nbg1"
      image       = "ubuntu-24.04"

      networks = [{
        network_id = module.network.network_id
        ip         = "10.0.1.10"
      }]
    }

    app-02 = {
      server_type = "cx23"
      location    = "fsn1"
      image       = "ubuntu-24.04"

      networks = [{
        network_id = module.network.network_id
        ip         = "10.0.1.11"
      }]
    }
  }

  common_ssh_keys = [12345]
  common_labels = {
    cluster    = "app"
    managed_by = "terraform"
  }
}

Complete Example with SSH Key Generation

# Generate SSH key.
module "ssh_key" {
  source  = "danylomikula/ssh-key/hcloud"
  version = "~> 1.0"

  create_key = true
  name       = "cluster-key"
  algorithm  = "ED25519"
}

# Create network.
module "network" {
  source  = "danylomikula/network/hcloud"
  version = "~> 1.0"

  create_network = true
  name           = "web-network"
  ip_range       = "10.100.0.0/16"

  subnets = {
    web = {
      type         = "cloud"
      network_zone = "eu-central"
      ip_range     = "10.100.1.0/24"
    }
  }
}

# Create servers.
module "server" {
  source  = "danylomikula/server/hcloud"
  version = "~> 1.0"

  servers = {
    web-1 = {
      server_type = "cx23"
      location    = "nbg1"
      image       = "ubuntu-24.04"

      networks = [{
        network_id = module.network.network_id
        ip         = "10.100.1.10"
      }]

      labels = {
        role = "webserver"
      }
    }
  }

  common_ssh_keys = [module.ssh_key.ssh_key_id]

  common_labels = {
    managed_by = "terraform"
  }
}

See complete example for a full working configuration.

Finding Available Server Types

Install hcloud CLI:

brew install hcloud

Setup guide: https://github.com/hetznercloud/cli/blob/main/docs/tutorials/setup-hcloud-cli.md

List server types:

hcloud server-type list

Locations

List locations:

hcloud location list

Documentation: https://docs.hetzner.com/cloud/general/locations/

Images

List available images:

# List all system images.
hcloud image list --type system

# Filter for specific OS.
hcloud image list --type system | grep ubuntu
hcloud image list --type system | grep rocky

Dynamic Image Selection with Data Source

Use hcloud_image data source to automatically select the latest image:

# Find latest Rocky Linux 9 for x86 architecture.
data "hcloud_image" "rocky9" {
  with_selector     = "os-flavor=rocky"
  with_architecture = "x86"
  most_recent       = true
}

# Find latest Ubuntu for ARM64.
data "hcloud_image" "ubuntu_arm" {
  name              = "ubuntu-24.04"
  with_architecture = "arm64"
}

# Use in server configuration.
module "servers" {
  source  = "danylomikula/server/hcloud"
  version = "~> 1.0"

  servers = {
    app-01 = {
      server_type = "cx23"
      image       = data.hcloud_image.rocky9.name  # Uses latest Rocky 9.
      location    = "nbg1"
    }

    app-arm = {
      server_type = "cax11"  # ARM64 server.
      image       = data.hcloud_image.ubuntu_arm.name
      location    = "fsn1"
    }
  }
}

Data source reference: https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs/data-sources/image

Available selectors:

  • os-flavor=ubuntu / rocky / debian / fedora
  • os-version=22.04 / 9 / 12

Architectures:

  • x86 - Standard Intel/AMD (cx, ccx series)
  • arm - ARM64 (cax series)

Best Practices

  1. Use private networks for inter-server communication.
  2. Enable backups for production servers.
  3. Apply firewalls to restrict access.
  4. Use placement groups for high availability.
  5. Set labels for organization and management.
  6. Use common_* variables** to reduce duplication.
  7. Generate SSH keys via the ssh-key module.

Lifecycle Considerations

The module uses ignore_changes for:

  • ssh_keys: Prevents recreation when keys are added manually.
  • user_data: Prevents recreation when cloud-init data changes.

Requirements

Name Version
terraform >= 1.12.0
hcloud >= 1.45.0

Providers

Name Version
hcloud >= 1.45.0

Modules

No modules.

Resources

Name Type
hcloud_server.this resource

Inputs

Name Description Type Default Required
common_firewall_ids List of firewall IDs to apply to all servers in addition to per-server firewalls. list(number) [] no
common_labels Labels to apply to all servers in addition to per-server labels. map(string) {} no
common_ssh_keys List of SSH key IDs to add to all servers in addition to per-server keys. list(number) [] no
servers Map of server configurations keyed by friendly name.
map(object({
server_type = string
location = optional(string)
datacenter = optional(string)
image = string
ssh_keys = optional(list(number), [])
keep_disk = optional(bool, false)
iso = optional(number)
rescue = optional(string)
backups = optional(bool, false)
ipv4_enabled = optional(bool, true)
ipv6_enabled = optional(bool, true)
firewall_ids = optional(list(number), [])
placement_group_id = optional(number)
user_data = optional(string)
labels = optional(map(string), {})
shutdown_before_deletion = optional(bool, false)
ignore_remote_firewall_ids = optional(bool, false)
rebuild_protection = optional(bool, false)
delete_protection = optional(bool, false)

networks = optional(list(object({
network_id = number
ip = optional(string)
alias_ips = optional(list(string), [])
})), [])

public_net = optional(object({
ipv4_enabled = optional(bool, true)
ipv6_enabled = optional(bool, true)
ipv4 = optional(number)
ipv6 = optional(number)
}))
}))
{} no

Outputs

Name Description
private_network_ips Map of server names to their private network IP addresses.
server_ids Map of server names to their IDs.
server_ipv4_addresses Map of server names to their IPv4 addresses.
server_ipv6_addresses Map of server names to their IPv6 addresses.
servers Map of all server resources with complete attributes.
servers_by_location Map of locations to lists of server IDs in each location.
servers_by_type Map of server types to lists of server IDs of each type.

Related Modules

Module Description GitHub Terraform Registry
terraform-hcloud-network Manage Hetzner Cloud networks and subnets GitHub Registry
terraform-hcloud-firewall Manage Hetzner Cloud firewalls GitHub Registry
terraform-hcloud-ssh-key Manage Hetzner Cloud SSH keys GitHub Registry

Authors

Module managed by Danylo Mikula.

Contributing

Contributions are welcome! Please read the Contributing Guide for details on the process and commit conventions.

License

Apache 2.0 Licensed. See LICENSE for full details.

Sponsor this project

Contributors 2

  •  
  •  

Languages