Expert coverage of Terraform network infrastructure automation: network providers (ACI, Meraki, PAN-OS, FortiOS, F5 BIG-IP), state management, plan/apply workflow, modules, remote state, and CI/CD integration for network IaC. Use for \"Terraform network\", \"Terraform ACI\", \"Terraform Meraki\", \"Terraform PAN-OS\", \"Terraform FortiOS\", \"Terraform F5\", \"Terraform provider network\", \"HCL network\", \"terraform plan network\". Do NOT use for cross-vendor comparison, platform selection,...
Pro scans all 2 files and shows the line behind each finding
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill terraform-network --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Terraform Network?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-terraform-network)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: terraform-network
description: "Expert coverage of Terraform network infrastructure automation: network providers (ACI, Meraki, PAN-OS, FortiOS, F5 BIG-IP), state management, plan/apply workflow, modules, remote state, and CI/CD integration for network IaC. Use for \"Terraform network\", \"Terraform ACI\", \"Terraform Meraki\", \"Terraform PAN-OS\", \"Terraform FortiOS\", \"Terraform F5\", \"Terraform provider network\", \"HCL network\", \"terraform plan network\". Do NOT use for cross-vendor comparison, platform selection, or category-wide architecture -- use the `network-automation` skill. Do NOT use for general-purpose Terraform (cloud infrastructure, state, modules, HCL language questions not targeting a network-device provider) -- that's the `terraform` skill (in the `devops` plugin)."
license: MIT
---
# Terraform Network Automation
This skill covers Terraform for network infrastructure automation across all supported provider versions. Areas of expertise include:
- Core Terraform workflow (init, plan, apply, destroy) applied to network infrastructure
- Network providers: CiscoDevNet/aci, cisco-open/meraki, paloaltonetworks/panos, fortiosapi/fortios, F5Networks/bigip
- State management for network resources (remote state, locking, state operations)
- Module design for reusable network infrastructure (VLAN modules, EPG modules, firewall rule modules)
- CI/CD integration (terraform plan in PR, terraform apply on merge)
- Drift detection via terraform plan
- Import of existing network resources into Terraform state
## How to Approach Tasks
1. **Classify** the request:
- **Provider usage** -- Identify the network platform and load provider documentation patterns
- **Architecture** -- Load `references/architecture.md` for provider details, state management, modules
- **State management** -- Apply remote state, locking, and state operation best practices
- **CI/CD** -- Design pipeline with plan/review/apply workflow
- **Migration** -- Import existing resources, or migrate between Terraform versions
2. **Identify the target platform** -- Which network provider (ACI, Meraki, PAN-OS, FortiOS, F5)? This determines the provider, resource types, and API interactions.
3. **Load context** -- Read the reference file for deep knowledge.
4. **Analyze** -- Apply Terraform network-specific reasoning. Network resources are stateful and often production-critical; plan/review/apply discipline is essential.
5. **Recommend** -- Provide complete, runnable HCL examples with provider configuration, resources, and variables.
6. **Verify** -- Suggest validation steps (terraform plan review, post-apply verification, state inspection).
## Core Workflow for Network
### Plan/Apply Discipline
Network infrastructure demands extra caution with Terraform:
```bash
terraform init # Download providers, initialize backend
terraform plan # Show what will change (ALWAYS review for network)
terraform apply # Apply after human review of plan
```
**Critical rule:** Never use `terraform apply -auto-approve` for production network changes without prior `terraform plan` review in CI.
### Destroy Caution
`terraform destroy` removes all managed resources. For network infrastructure:
- Destroying a tenant, VRF, or VLAN can cause production outages
- Use `terraform state rm` to stop managing a resource without deleting it
- Use `lifecycle { prevent_destroy = true }` on critical resources
- Never run `terraform destroy` on production without explicit change approval
## Provider Reference
### CiscoDevNet/aci (Cisco ACI)
Best suited for ACI fabric automation (tenants, VRFs, BDs, EPGs, contracts):
```hcl
provider "aci" {
username = var.aci_username
password = var.aci_password
url = "https://apic.example.com"
insecure = true # Skip TLS verify for lab; use certs in production
}
resource "aci_tenant" "prod" {
name = "PROD"
description = "Production Tenant"
}
resource "aci_vrf" "prod_vrf" {
tenant_dn = aci_tenant.prod.id
name = "PROD_VRF"
}
resource "aci_bridge_domain" "app_bd" {
tenant_dn = aci_tenant.prod.id
name = "APP_BD"
relation_fv_rs_ctx = aci_vrf.prod_vrf.id
}
resource "aci_application_profile" "app" {
tenant_dn = aci_tenant.prod.id
name = "APP_PROFILE"
}
resource "aci_application_epg" "web_epg" {
application_profile_dn = aci_application_profile.app.id
name = "WEB_EPG"
relation_fv_rs_bd = aci_bridge_domain.app_bd.id
}
```
### cisco-open/meraki (Cisco Meraki)
Cloud-managed network resources via Meraki Dashboard API:
```hcl
provider "meraki" {
api_key = var.meraki_api_key
}
resource "meraki_networks_vlans" "office_vlans" {
network_id = var.network_id
id = 10
name = "CORP_USERS"
subnet = "192.168.10.0/24"
appliance_ip = "192.168.10.1"
}
```
### paloaltonetworks/panos (Palo Alto PAN-OS)
Firewall policy, objects, NAT, and security profiles:
```hcl
provider "panos" {
hostname = var.panos_hostname
username = var.panos_username
password = var.panos_password
}
resource "panos_address_object" "web_servers" {
name = "WEB_SERVERS"
type = "ip-netmask"
value = "10.10.10.0/24"
}
resource "panos_security_policy" "allow_web" {
rule {
name = "ALLOW_WEB_OUT"
source_zones = ["trust"]
destination_zones = ["untrust"]
applications = ["web-browsing", "ssl"]
services = ["application-default"]
source_addresses = [panos_address_object.web_servers.name]
destination_addresses = ["any"]
action = "allow"
}
}
```
### fortiosapi/fortios (FortiGate FortiOS)
FortiGate firewall and SD-WAN configuration:
```hcl
provider "fortios" {
hostname = var.fortigate_ip
token = var.fortigate_api_token
insecure = false
}
resource "fortios_firewall_address" "internal_net" {
name = "INTERNAL_NET"
type = "ipmask"
subnet = "10.0.0.0 255.0.0.0"
comment = "Internal networks"
}
```
### F5Networks/bigip (F5 BIG-IP)
Load balancer nodes, pools, virtual servers:
```hcl
provider "bigip" {
address = "https://192.168.1.1"
username = "admin"
password = var.bigip_password
}
resource "bigip_ltm_node" "app_node" {
name = "/Common/app-server-1"
address = "192.168.10.11"
}
resource "bigip_ltm_pool" "app_pool" {
name = "/Common/APP_POOL"
load_balancing_mode = "least-connections-member"
monitors = ["/Common/http"]
}
resource "bigip_ltm_pool_attachment" "app_member" {
pool = bigip_ltm_pool.app_pool.name
node = "/Common/app-server-1:80"
}
```
## State Management
### Remote State (Required for Teams)
```hcl
terraform {
backend "s3" {
bucket = "network-terraform-state"
key = "production/aci/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
```
**State locking**: DynamoDB table prevents concurrent applies. Essential for team environments where multiple engineers might run Terraform simultaneously.
### State File Organization
Organize state per environment and per platform:
```
states/
├── production/
│ ├── aci/terraform.tfstate
│ ├── meraki/terraform.tfstate
│ ├── panos/terraform.tfstate
│ └── f5/terraform.tfstate
└── lab/
├── aci/terraform.tfstate
└── panos/terraform.tfstate
```
Each state file should contain related resources. Do not put all network resources in one state file (blast radius too large).
### State Operations
```bash
# List resources in state
terraform state list
# Show specific resource
terraform state show aci_tenant.prod
# Remove resource from state (stop managing, do not delete)
terraform state rm aci_application_epg.legacy_epg
# Import existing resource into state
terraform import aci_tenant.existing_tenant uni/tn-EXISTING
# Move resource between states (refactoring)
terraform state mv aci_vrf.prod aci_vrf.production
```
## Module Design
### Reusable Network Module Example
```hcl
# modules/aci_epg/main.tf
variable "tenant_name" { type = string }
variable "app_profile_name" { type = string }
variable "epg_name" { type = string }
variable "bd_name" { type = string }
variable "vrf_name" { type = string }
resource "aci_application_epg" "epg" {
application_profile_dn = "uni/tn-${var.tenant_name}/ap-${var.app_profile_name}"
name = var.epg_name
relation_fv_rs_bd = "uni/tn-${var.tenant_name}/BD-${var.bd_name}"
}
output "epg_dn" {
value = aci_application_epg.epg.id
}
```
Usage:
```hcl
module "web_epg" {
source = "./modules/aci_epg"
tenant_name = "PROD"
app_profile_name = "WEB_APP"
epg_name = "WEB_EPG"
bd_name = "WEB_BD"
vrf_name = "PROD_VRF"
}
```
### for_each for Bulk Resources
```hcl
variable "vlans" {
type = map(object({
name = string
subnet = string
}))
default = {
"10" = { name = "MGMT", subnet = "10.0.10.0/24" }
"20" = { name = "USERS", subnet = "10.0.20.0/24" }
"30" = { name = "VOICE", subnet = "10.0.30.0/24" }
}
}
resource "meraki_networks_vlans" "vlans" {
for_each = var.vlans
network_id = var.network_id
id = each.key
name = each.value.name
subnet = each.value.subnet
appliance_ip = cidrhost(each.value.subnet, 1)
}
```
## NetBox Integration
Query NetBox as source of truth and drive Terraform resources:
```hcl
data "http" "netbox_devices" {
url = "${var.netbox_url}/api/dcim/devices/?site=NYC&status=active"
request_headers = {
Authorization = "Token ${var.netbox_token}"
}
}
locals {
devices = jsondecode(data.http.netbox_devices.response_body).results
device_map = { for d in local.devices : d.name => d }
}
# Use NetBox data to drive resource creation
resource "aci_application_epg" "device_epgs" {
for_each = local.device_map
application_profile_dn = aci_application_profile.app.id
name = "${each.key}_EPG"
}
```
## Common Pitfalls
1. **terraform apply -auto-approve in production** -- Never auto-approve network changes. A bad plan applied automatically can disconnect production networks. Always review the plan.
2. **Single state file for everything** -- One massive state file means any `terraform apply` can affect any resource. Split by platform, environment, and functional area.
3. **Not using lifecycle prevent_destroy** -- Critical network resources (tenants, VRFs, core policies) should have `prevent_destroy = true` to prevent accidental deletion.
4. **Ignoring provider version pinning** -- Provider updates can change resource behavior. Pin provider versions in `required_providers` block.
5. **State file in Git** -- Never commit `terraform.tfstate` to Git. It contains sensitive data (API keys, passwords). Use remote state backends.
6. **Destroying before understanding dependencies** -- Network resources have dependencies (EPG depends on BD, BD depends on VRF). Terraform handles ordering, but understanding the dependency graph prevents surprises.
7. **Importing without planning** -- When importing existing resources, always `terraform plan` after import to verify Terraform's understanding matches reality. Adjust HCL until plan shows no changes.
8. **No remote state locking** -- Without locking, concurrent applies corrupt state. Always configure state locking (DynamoDB for S3, blob lease for Azure).
## Reference Files
Load these when you need deep knowledge:
- `references/architecture.md` -- Provider details, state management, plan/apply workflow, modules, NetBox integration patterns. Read for "how does X work" architecture questions.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!