Using Terraform to Manage Your Home Network
“You use Terraform… for your home network?”
Yes. And before you judge me, hear me out.
The Problem
My homelab has grown to around 25+ services, each needing DNS records, tunnel routes, firewall rules, and various network configs. Managing this through web UIs was fine when I had three services. At twenty-five, it’s a nightmare.
Every change meant logging into Cloudflare, clicking around, hoping I remembered which settings I changed last time. UniFi’s controller UI is nice but there’s no “undo” button. One wrong firewall rule and I’m locked out of my own network at 11 PM on a Tuesday.
Enter Terraform
I now manage my entire network stack as code:
- Cloudflare. DNS records, tunnel config, Zero Trust policies, WAF rules
- UniFi. Networks, WiFi configs, firewall rules, DHCP reservations
- Everything connects. UniFi network subnets automatically feed into Cloudflare tunnel routes
module "cloudflare" {
source = "./cloudflare"
services = {
hassio = {
subdomain = "hassio"
service_url = "http://traefik:80"
}
grafana = {
subdomain = "grafana"
service_url = "http://traefik:80"
}
# ... 20 more services
}
network_subnets = module.unifi.network_subnets
}
Adding a new service to the tunnel is three lines in a tfvars file. terraform plan shows me exactly what will change. terraform apply makes it happen. If I mess up, git revert and reapply.
What This Actually Looks Like
My repo structure:
networking/terraform/
├── main.tf # Root module, wires everything together
├── variables.tf # All the knobs
├── cloudflare/
│ ├── main.tf # Tunnel, DNS, ingress rules
│ ├── zero-trust.tf # WARP, access policies
│ └── variables.tf
└── unifi/
├── networks.tf # VLANs, subnets
├── firewall.tf # Inter-VLAN rules
├── wifi.tf # SSIDs and passwords
└── variables.tf
Every change goes through a PR (yes, to myself). The plan output is my review checklist. I merge, apply, and the network updates.
The Real Benefits
Disaster recovery. My Mac Mini died once. Rebuilt the whole networking stack from the repo in under an hour. Without Terraform, that would have been a full weekend of “what was the DNS record for that thing again?”
Documentation by default. Every resource has a name, a comment, and a reason for existing. Six months from now, I won’t remember why I opened port 21065. The Terraform code will.
Drift detection. terraform plan tells me if someone (me, at 2 AM) changed something through the UI without updating the code. No more mystery configurations.
Fearless changes. Need to restructure my VLANs? Terraform shows me every downstream impact before I touch anything. That confidence is worth the setup cost alone.
The Honest Cost
Setting this up took a weekend. The Cloudflare provider is solid. The UniFi provider is… less solid. There are quirks, undocumented behaviors, and the occasional “why did that import break everything?”
State management is the other thing. I keep terraform.tfstate in the repo (it’s a private repo, don’t @ me). For a homelab, this is fine. For anything else, use remote state.
And the tfvars file has secrets in it. It’s gitignored, backed up separately, and I accept that I’m one git add -A away from leaking my API tokens. Life on the edge.
Is It Overkill?
Absolutely. But here’s the thing about “overkill” in a homelab. there’s no such thing if you’re learning. I use Terraform at work now with confidence I wouldn’t have without this project. The homelab is a playground where mistakes don’t page anyone.
If you’re running more than five services and you’re tired of clicking through UIs, give it a shot. Start with just Cloudflare DNS. it’s the easiest win. You’ll wonder why you ever managed DNS records by hand.
terraform init
terraform plan
# Look at the plan. Really look at it.
terraform apply
Three commands. Your entire network, version-controlled. Future you will be grateful.
Related
- Why I Self-Host Everything: the philosophy behind running your own infrastructure at home
- Kubernetes Is Not the Answer for Everything: when to reach for Docker Compose instead, and when K8s actually earns its complexity
- Immutable Backups with Airgapper: protecting the data your IaC stack runs on top of