Terraform module for managing Hetzner Cloud firewalls with multiple rules.
- Create multiple firewalls with custom rules
- Support for inbound and outbound rules
- Flexible port and IP restrictions
- Common labels across all firewalls
- Rich outputs for integration
module "firewall" {
source = "danylomikula/firewall/hcloud"
version = "~> 1.0"
firewalls = {
web = {
rules = [
{
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["YOUR_IP/32"]
description = "allow ssh from my ip"
},
{
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
description = "allow http from anywhere"
},
{
direction = "in"
protocol = "tcp"
port = "443"
source_ips = ["0.0.0.0/0", "::/0"]
description = "allow https from anywhere"
}
]
}
}
}module "firewall" {
source = "danylomikula/firewall/hcloud"
version = "~> 1.0"
firewalls = {
web = {
rules = [
{
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["YOUR_IP/32"]
description = "ssh access"
},
{
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
description = "http traffic"
}
]
}
}
common_labels = {
environment = "production"
managed_by = "terraform"
}
}
module "server" {
source = "danylomikula/server/hcloud"
version = "~> 1.0"
servers = {
web-01 = {
server_type = "cx23"
location = "nbg1"
image = "ubuntu-24.04"
ssh_keys = [var.ssh_key_id]
}
}
common_firewall_ids = [module.firewall.firewall_ids["web"]]
}{
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["1.2.3.4/32"]
description = "ssh from office"
}{
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
description = "http traffic"
},
{
direction = "in"
protocol = "tcp"
port = "443"
source_ips = ["0.0.0.0/0", "::/0"]
description = "https traffic"
}{
direction = "in"
protocol = "tcp"
port = "5432"
source_ips = ["10.100.0.0/16"]
description = "postgres from private network"
}{
direction = "in"
protocol = "tcp"
port = "8000-8999"
source_ips = ["0.0.0.0/0"]
description = "application ports"
}{
direction = "in"
protocol = "icmp"
source_ips = ["0.0.0.0/0", "::/0"]
description = "allow ping"
}{
direction = "out"
protocol = "tcp"
port = "443"
destination_ips = ["0.0.0.0/0", "::/0"]
description = "allow outbound https"
}{
name = string # optional, defaults to map key
labels = map(string)
rules = list(object({
direction = string # "in" or "out"
protocol = string # "tcp", "udp", "icmp", "esp", "gre"
port = string # port or port range (e.g., "80" or "8000-8999")
source_ips = list(string) # cidr blocks for inbound rules
destination_ips = list(string) # cidr blocks for outbound rules
description = string # optional description
}))
}- tcp: Transmission Control Protocol
- udp: User Datagram Protocol
- icmp: Internet Control Message Protocol (for ping)
- esp: Encapsulating Security Payload (for VPN)
- gre: Generic Routing Encapsulation (for VPN)
- Restrict SSH Access: Limit SSH (port 22) to known IPs only
- Allow ICMP: Enable ping for monitoring and debugging
- Use Descriptions: Document each rule's purpose
- Group by Service: Create separate firewalls for different services
- Use common_labels: Apply consistent labels for organization
- Private Network Traffic: Allow internal traffic from private network ranges
- Default Deny: Hetzner firewalls deny all traffic by default, explicitly allow what you need
- Firewalls can be attached to multiple servers
- Rules are stateful (return traffic is automatically allowed)
- Default policy is deny all (whitelist approach)
- Changes to firewall rules apply immediately to all attached servers
- IPv6 should be included in source_ips with
::/0for public access
List Firewalls:
hcloud firewall listDescribe Firewall:
hcloud firewall describe <firewall-id>| Name | Version |
|---|---|
| terraform | >= 1.5.0 |
| hcloud | >= 1.45.0 |
| Name | Version |
|---|---|
| hcloud | >= 1.45.0 |
No modules.
| Name | Type |
|---|---|
| hcloud_firewall.this | resource |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| common_labels | Labels to apply to all firewalls. | map(string) |
{} |
no |
| firewalls | Map of firewall configurations. | map(object({ |
{} |
no |
| Name | Description |
|---|---|
| firewall_ids | Map of firewall names to their IDs. |
| firewalls | Map of all firewall resources with complete attributes. |
| Module | Description | GitHub | Terraform Registry |
|---|---|---|---|
| terraform-hcloud-network | Manage Hetzner Cloud networks and subnets | GitHub | Registry |
| terraform-hcloud-ssh-key | Manage Hetzner Cloud SSH keys | GitHub | Registry |
| terraform-hcloud-server | Manage Hetzner Cloud servers | GitHub | Registry |
Module managed by Danylo Mikula.
Contributions are welcome! Please read the Contributing Guide for details on the process and commit conventions.
Apache 2.0 Licensed. See LICENSE for full details.