Hetzner Private Network + NAT
Private network with subnets, routes, and a NAT gateway server for egress-only fleets.
Verification
Static-verifiedPassed: validated and lint-clean (provider-schema-validated for AWS/Azure/GCP; Terraform-language lint elsewhere).
Conformance
- Static validation (fmt · validate · tflint)
- No applicable security policies for this provider
- Plan tests (mocked: validation rules · outputs)
Provenance
- SHA-256 checksum
- Cosign signature
Functional
- Live test pending (no cloud run yet)
Last verified 2026-06-28 · how we verify
Verify this download
cosign · sha-256Don't take our word for it. Every release is signed with cosign - check the bytes against our pinned public key before you trust them.
# 1. Our pinned public key - fetch once, trust out-of-band
curl -O https://www.iac-bazaar.com/cosign.pub
# 2. This module's Sigstore bundle
curl -o hetzner-private-network-1.0.0.sigstore.json \
https://www.iac-bazaar.com/api/artifacts/hetzner-private-network/signature
# 3. Verify the tarball you downloaded
cosign verify-blob \
--key cosign.pub \
--bundle hetzner-private-network-1.0.0.sigstore.json \
hetzner-private-network-1.0.0.tar.gz
# → Verified OK
# 4. (optional) confirm the checksum too
echo "2bc748f50756a9838c60e5f87d1f79abea5284ce33b5876eb7103c0821dbe375 hetzner-private-network-1.0.0.tar.gz" | sha256sum -cUse it from the registry
terraform · opentofumodule "private_network" {
source = "www.iac-bazaar.com/iac-bazaar/hetzner-private-network/hetzner"
version = "1.0.0"
}Needs a registry token from /account/tokens. The module itself is free; the account is what identifies you. Full setup: registry docs.
Cite it in your README
badge · attributionPaste this beside the module in the repository that uses it. The badge is rendered from this artifact's verification record, so it reads static-verified because the record says so, and the link lands on this page.
[](https://www.iac-bazaar.com/catalog/hetzner-private-network?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)
Terraform module 1.0.0, static-verified on IaC Bazaar: [Hetzner Private Network + NAT](https://www.iac-bazaar.com/catalog/hetzner-private-network?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)
```hcl
module "private_network" {
source = "www.iac-bazaar.com/iac-bazaar/hetzner-private-network/hetzner"
version = "1.0.0"
}
```Preview:
Inputs & outputs
Create a free account to read this module's contract
The declared contract - every input name, type, default and description, plus every output - is shown to signed-in accounts, not to anonymous visitors.
A free account sees the contract of every module in the catalogue. There is no subscription and nothing to buy - the modules are free to download, and they run under Vizier.
Documentation
hetzner-private-network
Status: static-validated, live-test pending. Ships under live-test quarantine — validated with
tofu fmt,tofu validate, andtflint. Real apply/verify/destroy testing is pending a Hetzner Cloud sandbox account.
Private network for Hetzner Cloud with cloud subnets, egress routes, and a
self-managed NAT gateway so egress-only fleets can reach the internet
without holding a public IPv4. One module call gives you an RFC1918 network,
one or more cloud subnets, a hardened NAT gateway server, and the
0.0.0.0/0 route that funnels private servers' outbound traffic through it.
Works with Terraform and OpenTofu (>= 1.6), hcloud provider
>= 1.0, < 2.0.
Design & secure defaults
- Private by default. The network and its subnets carry no public exposure. The only resource with an internet-facing address is the (optional) NAT gateway, and it gets exactly one public IPv4.
- Deny-by-default gateway firewall. No inbound port is open on the NAT
gateway — not even SSH — until you allowlist
nat_gateway_ssh_source_ips. Only ICMP is allowed. Outbound stays open so MASQUERADE can work. - NAT is a pattern, not a managed service. Hetzner has no managed NAT
gateway. This module provisions a small server with a fixed private IP,
enables IPv4 forwarding, and installs a persistent
iptables MASQUERADErule via cloud-init. You operate and patch this server — keep SSH key access on it (nat_gateway_ssh_key_ids) and apply OS updates. It is a single instance, so it is also a single point of failure for egress; for HA you would front two gateways yourself. - Stable route target. The gateway's private IP is computed deterministically
(
cidrhost(subnet, nat_gateway_host_index)) and reused as the route gateway, so the egress route always points at the right host. A precondition rejects the network's reserved first IP. - One-flag delete protection across the network and the gateway server.
Egress-only servers you create elsewhere simply attach to one of these subnets
with ipv4_enabled = false; the network route does the rest.
Requirements
- Terraform or OpenTofu
>= 1.6 hetznercloud/hcloudprovider>= 1.0, < 2.0(private networks, subnets, routes andhcloud_server_network— latest recommended)
License
Commercial — LicenseRef-IaCBazaar-Commercial. See the IaC Bazaar terms.
Usage code & full reference need an account
The complete copy-paste usage, the full input/output reference, and operational notes are free with an account - shown here and bundled in the download. Sign in and this section fills in.
- Usage
- Inputs
- Outputs
- Notes
Related modules
huawei-vpc
A Huawei Cloud VPC whose range is checked against RFC 1918 (a public range by name), with subnets placed in the zones you name, each with its gateway at the first address and DHCP handing out Huawei's resolvers so the platform's service names resolve. Nothing egresses: a NAT gateway (huawei-nat-gateway) or an EIP is a separate decision.
do-vpc
Every resource created without a vpc_uuid lands in the region's default VPC beside everything the team ever made there; an auto-assigned ip_range is the one most likely to collide with the next peer; and a peering between overlapping ranges is accepted and carries nothing. A named VPC, a required range, overlaps refused at plan time, and an output that says nothing inside the VPC is filtered.
civo-network
Every resource created without a network_id lands in the region's default network beside everything the team ever made there; cidr_v4 is optional, so a network created without it gets whatever range was free, the one most likely to collide with the office or the VPN. A named network, a required range, the resolvers you chose, and an output that says the network itself filters nothing.
exoscale-private-network
A private network without start, end and netmask hands out no addresses: every instance configures its own and two that pick the same one collide silently; and nothing filters traffic on the segment. A managed range required and derived from your RFC 1918 CIDR, addresses reserved at the ends for gateways, and an output that says every attached instance reaches every other.
upcloud-network
A private network on a public range is the surprise at the first NAT, and dhcp_default_route defaults to false, so servers get an address and no route, right for an isolated segment and wrong for one behind a router. An RFC 1918 range required, DHCP handing out the resolvers you chose, a router created and the default route set when you ask, and an output that says the network filters nothing.
ovh-private-network
A private network is a vRack VLAN that carries no addresses until a subnet hands them out; a subnet without a gateway address has no way to the internet; and nothing filters traffic on the segment. The subnet's RFC 1918 range required, DHCP with the resolvers you chose, an OVH gateway created by default so instances reach out without a public address, the network named as unfiltered.