Terraform is everywhere for cloud resources. It is far less common for network gear, which is a shame: the state machine model fits declarative network configuration surprisingly well. Here are the patterns that survive contact with a real production network.
Why Terraform for Networks?
The usual argument for Ansible in networking is flexibility — you can conditionally push config, handle vendor quirks, and react to state. The argument for Terraform is idempotency with drift detection: terraform plan tells you exactly what will change before you change it, and the state file tracks divergence between declared and actual config.
Both tools have their place. The pattern that works at scale is: Terraform for persistent, long-lived network state (VLANs, BGP peers, firewall policies, DNS records) and Ansible for operational tasks (rolling upgrades, log collection, one-time remediations).
Remote State First
The single biggest mistake in Terraform network projects is local state. State must live in a shared backend from day one. For a network team:
terraform {
backend "s3" {
bucket = "mycompany-tf-state"
key = "network/prod/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "tf-state-lock"
encrypt = true
}
}
DynamoDB locking prevents concurrent applies. If two engineers run terraform apply simultaneously without a lock, you get state corruption. This is not theoretical — it happens on the first week of a team adopting Terraform.
Module Structure for Network Infrastructure
A flat Terraform project that manages an entire network is unmanageable by month three. The structure that scales:
modules/
network-segment/ # VLANs, prefixes, routing instances
firewall-policy/ # Rule sets, NAT, VIP
bgp-peer/ # Peer config, prefix filters
dns-zone/ # Records, TTL management
environments/
prod/
staging/
lab/
Each environment consumes the modules with environment-specific variables. The modules handle the logic; the environments handle the values.
The NetBox Provider Pattern
The netbox Terraform provider (maintained by the community, ~2k downloads/week) lets you declare network objects in NetBox from Terraform, then consume them in your infrastructure config:
# Declare a prefix in NetBox
resource "netbox_prefix" "dmz_segment" {
prefix = "10.200.1.0/24"
status = "active"
description = "DMZ — web tier"
vrf_id = data.netbox_vrf.prod.id
site_id = data.netbox_site.paris.id
}
# Use that prefix in Palo Alto policy
resource "panos_security_policy" "allow_dmz_outbound" {
source_zones = ["dmz"]
destination_zones = ["internet"]
source_addresses = [netbox_prefix.dmz_segment.prefix]
# ...
}
This creates a documented chain: NetBox is the SoT, Terraform is the executor, and the firewall state is always derivable from the Terraform state.
Handling Stateful Network Devices
Network devices are not stateless cloud resources. A BGP session has its own state that Terraform cannot directly observe. The pattern for this is lifecycle + ignore_changes:
resource "junos_bgp_neighbor" "upstream" {
ip = "203.0.113.1"
local_as = 65001
peer_as = 65002
description = "Upstream provider A"
lifecycle {
# Don't touch operational state managed by the router
ignore_changes = [established_count, flap_count]
}
}
For anything that genuinely cannot be managed declaratively (vendor-specific quirks, one-time migrations), use a null_resource with a local-exec provisioner and document why.
Testing Before You Push
The pattern that reduces production incidents: plan-then-apply in CI, with a mandatory human review of the plan output for anything touching production.
# GitLab CI / GitHub Actions pattern
plan:
script:
- terraform init
- terraform plan -out=tfplan -detailed-exitcode
artifacts:
paths: [tfplan]
apply:
when: manual
environment: production
script:
- terraform apply tfplan
-detailed-exitcode returns exit code 2 when there are changes (rather than 0 = success). This lets the CI pipeline surface “changes pending” as a distinct state from “no changes needed.”
Key Providers for Network Teams
| Provider | Use case |
|---|---|
netbox | Source of Truth objects |
panos | Palo Alto Networks |
junos | Juniper Junos |
arista_eos | Arista EOS |
aws / azurerm | Cloud networking (VPC, VNet, Transit GW) |
cloudflare | DNS, WAF, CDN |
infoblox | IPAM + DNS |
Training
The Terraform training at Sphinx-Digital covers all of this: remote state, modules, CI/CD integration, and provider deep-dives including the NetBox and cloud networking providers. 3 days of labs on real AWS infrastructure.