Infrastructure as Code for Networking (Terraform + Cisco)
Home › Network Automation › Infrastructure as Code for Networking
A practical guide for network engineers: how Terraform works, the Cisco provider ecosystem, real HCL config examples, state management, and a CI/CD pipeline for network changes
By Route XP | Published: March 2026 | Network Automation, Cisco, Data Center
1. Why Network Engineers Need IaC
Network infrastructure has historically been configured the same way for decades — an engineer SSH's into a device, types commands, and hopes the running config matches what they intended. This approach doesn't scale, doesn't self-document, and has no rollback mechanism beyond a saved config file buried in someone's laptop.
Infrastructure as Code (IaC) applies software engineering discipline to network configuration: your network topology, VLANs, routing policies, and firewall rules are declared in version-controlled code files. Changes go through a review process. Every state transition is tracked. A misconfiguration is a git revert away from recovery.
For Cisco environments specifically — which often span ACI data centers, IOS-XE campus switches, SD-WAN fabrics, and Meraki cloud-managed sites — Terraform provides a single, consistent workflow to manage all of it declaratively, regardless of the underlying API.
2. How Terraform Works: Core Concepts
Terraform, built by HashiCorp (now part of IBM), uses a plugin-based architecture where providers translate HCL resource declarations into API calls for specific platforms. The workflow is always the same three commands, regardless of whether you're configuring AWS, a Cisco ACI fabric, or a Meraki dashboard.
The Terraform Workflow
terraform init
# 2. Plan — shows exactly what will change, nothing is applied yet
terraform plan -out=tfplan
# 3. Apply — executes the planned changes
terraform apply tfplan
The power is in terraform plan. Before touching a single device, Terraform prints a human-readable diff of every resource it intends to create, modify, or destroy. This is your change review step — it can be posted to a pull request, reviewed by a senior engineer, and approved before apply is ever run.
Core Building Blocks
| Concept | What It Is | Network Example |
|---|---|---|
| Provider | Plugin that translates HCL into platform API calls | hashicorp/ciscoaci, ciscodevnet/iosxe |
| Resource | A managed infrastructure object — created, updated, or destroyed by Terraform | A VLAN, a BGP neighbour, an ACI EPG |
| Data Source | Read-only query of existing infrastructure — not managed by Terraform | Look up an existing ACI tenant ID to reference in a new EPG |
| Variable | Parameterise your configuration for reuse across environments | var.vlan_id, var.bgp_as_number |
| Module | Reusable package of resources — your "network design patterns as code" | A module that builds a full leaf-spine pair with standard policies |
| State | Terraform's record of what it has deployed — the source of truth for drift detection | terraform.tfstate — store remotely, never locally in production |
3. The Cisco Provider Ecosystem
Cisco has invested significantly in Terraform provider coverage across its portfolio. Each provider communicates with its platform via a different underlying API — REST, NETCONF/RESTCONF, or a platform-specific SDK — but the HCL workflow is identical from the engineer's perspective.
| Provider | Platform | Underlying API | Registry Namespace |
|---|---|---|---|
| ACI | Cisco ACI / APIC | APIC REST API | hashicorp/aci |
| IOS-XE | Catalyst, ISR, CSR1000v | RESTCONF (RFC 8040) | CiscoDevNet/iosxe |
| Meraki | Meraki Dashboard | Meraki Dashboard REST API | CiscoDevNet/meraki |
| NX-OS | Nexus switches | NX-API REST / JSON-RPC | CiscoDevNet/nxos |
| Intersight | Cisco Intersight (UCS, HyperFlex) | Intersight REST API | CiscoDevNet/intersight |
4. Real HCL Examples: ACI, IOS-XE, Meraki
Example 1 — Cisco ACI: Create a Tenant and VRF
This example provisions a new ACI tenant, a VRF, and a Bridge Domain — three of the most common day-one operations on an ACI fabric.
terraform {
required_providers {
aci = {
source = "hashicorp/aci"
version = "~> 2.9"
}
}
}
provider "aci" {
username = var.apic_username
password = var.apic_password
url = var.apic_url
insecure = false
}
# main.tf — Tenant + VRF + Bridge Domain
resource "aci_tenant" "prod" {
name = "PROD-Tenant"
description = "Production workloads"
}
resource "aci_vrf" "prod_vrf" {
tenant_dn = aci_tenant.prod.id
name = "PROD-VRF"
ip_data_plane_learning = "enabled"
}
resource "aci_bridge_domain" "web_bd" {
tenant_dn = aci_tenant.prod.id
name = "WEB-BD"
relation_fv_rs_ctx = aci_vrf.prod_vrf.id
arp_flood = "no"
unicast_route = "yes"
}
Example 2 — IOS-XE: Configure a BGP Neighbour
The IOS-XE provider uses RESTCONF under the hood. From the engineer's perspective it is just HCL — no YANG models to hand-craft manually.
host = "https://192.0.2.1"
username = var.ios_username
password = var.ios_password
}
resource "iosxe_bgp" "core_bgp" {
asn = "65001"
router_id = "10.0.0.1"
}
resource "iosxe_bgp_neighbor" "peer1" {
asn = "65001"
ip = "10.0.0.2"
remote_as = "65002"
description = "WAN-Peer-DC2"
update_source_loopback = "0"
ebgp_multihop = 2
}
Example 3 — Meraki: Create a Network and Push an SSID
meraki_api_key = var.meraki_api_key
}
resource "meraki_networks" "branch_london" {
organization_id = var.org_id
name = "Branch-London"
product_types = ["wireless", "switch", "appliance"]
timezone = "Europe/London"
}
resource "meraki_networks_wireless_ssids" "corp_wifi" {
network_id = meraki_networks.branch_london.network_id
number = 0
name = "Corp-WiFi"
enabled = true
auth_mode = "8021x-radius"
encryption_mode = "wpa"
wpa_encryption_mode = "WPA2 Enterprise"
}
terraform plan to preview, apply to execute. The learning curve is the HCL syntax and the specific resource attributes — not a new workflow per platform.
5. State Management and Remote Backends
Terraform's state file (terraform.tfstate) is a JSON record mapping every HCL resource to the real object it created on the network. It is how Terraform knows that aci_tenant.prod corresponds to tenant DN uni/tn-PROD-Tenant in your ACI fabric. Without state, every plan would appear to need a full re-creation of all resources.
terraform.tfstate file on one engineer's machine means other team members cannot run Terraform safely — and if that file is lost, Terraform loses track of all managed resources. Always use a remote backend from day one.
Remote backends store state in a shared, versioned, locking-capable store. Common options for network teams:
| Backend | State Locking | Best For |
|---|---|---|
| HCP Terraform (Terraform Cloud) | ✅ Built-in | Teams wanting managed runs, UI, and approval workflows |
| AWS S3 + DynamoDB | ✅ DynamoDB lock | AWS-native environments; cheap and widely understood |
| Azure Blob Storage | ✅ Blob lease lock | Azure-native environments |
| GitLab Managed Terraform State | ✅ Built-in | Teams already using GitLab CI/CD for network pipelines |
State also enables drift detection. Running terraform plan against a stable environment shows any resource that has been changed out-of-band — for example, a VLAN deleted manually via the APIC GUI. This is one of the most operationally valuable capabilities of Terraform for network teams: it makes ad-hoc manual changes visible and revertible.
6. CI/CD Pipeline for Network Changes
The real transformation that IaC enables is treating network changes exactly like software deployments — with automated validation, peer review, and staged rollout. Here is a representative GitLab CI pipeline for a Cisco network change:
stages:
- validate
- plan
- apply
validate:
stage: validate
script:
- terraform init -backend=false
- terraform validate
- terraform fmt -check -recursive
plan:
stage: plan
script:
- terraform init
- terraform plan -out=tfplan
artifacts:
paths: [tfplan]
# Plan output posts to MR as a comment for peer review
apply:
stage: apply
when: manual # Requires explicit approval — never auto-apply
only: [main] # Only runs on merge to main branch
script:
- terraform apply tfplan
This pipeline enforces a critical discipline: no network change is applied without a plan artifact being reviewed and manually approved. The when: manual gate on the apply stage means a human must click "Run" in GitLab after reviewing the plan output posted to the merge request. This is the change management process — it's just automated.
7. Best Practices and Pitfalls
| ✅ Do | 🚫 Don't |
|---|---|
Store secrets (passwords, API keys) in a vault — pass to Terraform via environment variables or Vault provider, never in .tfvars committed to Git |
Commit secrets to any Git repository — even private ones. Rotate any key that has been accidentally committed immediately |
Use terraform import to bring existing manually-created resources under Terraform management — don't start from a blank slate if the network already exists |
Run terraform apply directly in production without a reviewed plan. Always plan first; treat the plan as your change record |
| Separate state files per environment (dev/staging/prod) and per network domain (ACI, IOS-XE, Meraki) — using Terraform workspaces or separate state backends | Manage all environments from a single state file — a mistake in one environment can affect others, and the blast radius of a terraform destroy is contained by state boundary |
| Use modules for repeatable patterns (e.g., a "standard branch network" module that creates VLANs, SVIs, and ACLs) — reduces copy-paste and enforces standards | Put everything in a single monolithic main.tf — split resources into logical files (routing.tf, vlans.tf, security.tf) for readability |
Pin provider versions with ~> 2.9 constraints — provider updates can change resource behaviour and break existing configurations |
Run terraform destroy on a production network without understanding the full dependency graph — Terraform will delete resources in dependency order, which may not match your expectation |
terraform plan against an empty configuration to understand what Terraform sees. Then use terraform import to bring existing resources into state one at a time. Attempting to re-create existing ACI objects by writing HCL without importing first will result in Terraform trying to create duplicate objects — which may fail loudly or, worse, create duplicates silently.
8. Frequently Asked Questions
Q: Do I need programming experience to use Terraform for networking?
No. HCL is a declarative configuration language, not a programming language — there are no loops, functions, or data structures to wrestle with for basic use cases. Most network engineers are productive with Terraform within a few days of learning the workflow. Familiarity with Git (commits, branches, pull requests) is more important than coding experience.
Q: What is the difference between Terraform and Ansible for network automation?
They solve different problems. Ansible is task-oriented and imperative — great for pushing configuration changes (run this playbook to update BGP timer values across 50 routers). Terraform is state-oriented and declarative — great for lifecycle management of network objects (create this ACI tenant with these EPGs; if I remove it from code, destroy it). Many teams use both: Terraform for provisioning the network infrastructure, Ansible for ongoing configuration management.
Q: Can Terraform roll back a network change?
Not automatically — Terraform is not a transaction system. To "roll back" you revert your HCL code to the previous version in Git and run terraform apply again. Terraform calculates the delta from the current state to the desired previous state and makes the necessary changes. This is why the plan review step is critical — it is your last line of defence before changes are applied.
Q: Is Terraform suitable for managing network devices that don't have a REST API?
For legacy IOS devices without RESTCONF, the netascode/iosxe provider can use NETCONF (SSH-based) on older IOS-XE versions. For truly legacy CLI-only devices, Ansible with the ios module via SSH is the better tool. Terraform works best with API-driven platforms — ACI, Meraki, and IOS-XE 16.12+ with RESTCONF enabled are all excellent targets.
📘 Facebook 🐦 Twitter 💼 LinkedIn
Technical content based on HashiCorp Terraform documentation, Cisco DevNet provider documentation for ACI, IOS-XE, Meraki, and NX-OS, and GitLab CI/CD reference architecture. HCL examples are illustrative and should be validated in a non-production environment. All provider versions current as of March 2026.