In part 1, Hetzner stood as an affordable, sovereign base. One sentence fell there almost in passing: that the integration into Terraform was the actual upside. That is exactly what this is about now.
My message, briefly: Terraform pays off from the first person in the IT team. Not from the fifth, not from a dedicated platform team — from one.
When it starts to pay off: from one
The objection comes immediately, and it is not stupid: clicking it together is faster. A console, a few clicks, the server runs. True — for the first weeks. Then comes the second server, a firewall rule here, a volume there, a DNS change "quickly in between". After a few months nobody reliably knows which configuration is the way it is, and why. At the latest with a hardware failure or a provider switch, the "quickly in between" turns into a day full of guesswork.
The point is not convenience but memory. A console does not remember why a rule exists. Git does.
What I use it for — and where the state lives
I describe with it all services that provision or influence infrastructure — in my case Hetzner and Cloudflare. Servers, volumes, firewalls, DNS, load balancers: all in code, all in Git.
My state lives in an S3-compatible bucket at Hetzner. The reason is not a technical end in itself but self-protection: the infrastructure is versioned, I keep the overview, and in a total outage the manual steps are minimal. For me — and for the clients who rely on it.
What it concretely saves
Three situations where the effort pays off: recovery after an outage, drift, and the setup of test systems.
Done manually, you always forget something. A firewall rule, a network setting, a volume that is mounted wrong or not at all. Each single detail is small. In sum it costs hours — and in an outage those are the most expensive hours there are.
This is how it starts — one server, one volume, a firewall that only lets in what should come in, and a cloud-init that hardens the box on its very first boot. All in files that live in Git:
resource "hcloud_server" "app" {
name = "app-01"
server_type = "ccx23"
image = "debian-12"
location = "nbg1"
firewall_ids = [hcloud_firewall.web.id]
user_data = file("cloud-init.yaml")
}
resource "hcloud_volume" "data" {
name = "app-data"
size = 100
server_id = hcloud_server.app.id
automount = true
format = "ext4"
}
resource "hcloud_firewall" "web" {
name = "web"
rule { # SSH only from your own IP
direction = "in"
protocol = "tcp"
port = "22"
source_ips = ["203.0.113.10/32"]
}
rule { # HTTPS open
direction = "in"
protocol = "tcp"
port = "443"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # only for the redirect to 443
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
}
}#cloud-config
# on first boot: hardening, not handwork
package_update: true
packages:
- fail2ban
- unattended-upgrades
users:
- name: deploy
groups: [sudo]
shell: /bin/bash
ssh_authorized_keys:
- ssh-ed25519 AAAA... deploy@laptop
ssh_pwauth: false
runcmd:
- echo 'PermitRootLogin no' >> /etc/ssh/sshd_config.d/hardening.conf
- echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config.d/hardening.conf
- systemctl restart ssh
- systemctl enable --now fail2banThat is all it is at the start. No module scaffold, no workspace construct — a handful of resources plus a cloud-init. But the server comes up reproducibly and hardened: fail2ban, no root login, no password SSH, port 22 only from your own IP. That is exactly what you reliably forget when clicking it together. The entry is small, the benefit immediate.
The overhead trap
And with that to the downside: Terraform tips into overhead when you overdo it. The most common mistake in small teams is the attempt to force everything into a single Terraform project — a "one-click" setup that maps every manual step.
My advice for the small team: not every manual step has to be in Terraform. Documentation, runbooks and a few shell scripts are not a failure but part of a healthy setup. Terraform maps the infrastructure — the rest may well be carried by a well-written runbook. Whoever forces the "one-click" ideal builds exactly the overhead Terraform was supposed to spare them.
Conclusion
In a small team, Terraform is not enterprise tooling you first have to be able to afford. It is the cheapest insurance against the day something fails or the provider changes. From one person it pays off — provided you map the infrastructure and not the whole world.
Part 3 closes the series; after that the mid-market stack is complete.
If your infrastructure has "grown historically" and nobody can say exactly what runs and why: that very cleanup — and the build of a setup a small team can carry — is part of my work in Technical Consulting.