Terraform automates Cisco ACI by letting you declare tenants, VRFs, bridge domains, EPGs, and contracts in HCL code files that are version-controlled, peer-reviewed, and applied through a repeatable init → plan → apply workflow. According to HashiCorp benchmarks, teams using Terraform for ACI provisioning see 5x faster deployment times and 80% fewer configuration errors compared to manual APIC GUI workflows. For CCIE Automation candidates, this is not optional knowledge — section 2.0 of the exam blueprint dedicates 30% to Infrastructure as Code.

Key Takeaway: Nexus-as-Code eliminates the HCL learning curve entirely — you define your ACI fabric in YAML files and let Cisco’s 150+ Terraform sub-modules handle the API translation, making production-grade IaC accessible to network engineers who have never written a line of code.

Why Should Network Engineers Learn Terraform for ACI?

Network engineers managing Cisco ACI fabrics face a fundamental scaling problem: the APIC GUI handles single-tenant provisioning well, but managing 50+ tenants across development, staging, and production environments through point-and-click workflows creates configuration drift, undocumented changes, and rollback nightmares. Terraform solves this by treating your ACI fabric configuration as code — every tenant, VRF, bridge domain, and EPG is declared in a file, tracked in Git, and deployed through an automated pipeline. According to The Network DNA (2026), the shift from imperative scripting to declarative IaC represents the single biggest operational improvement available to data center network teams today.

The business case is straightforward. Manual ACI provisioning through the APIC GUI takes 15-30 minutes per tenant with VRF, bridge domain, and EPG creation. A Terraform apply completes the same work in under 60 seconds. Multiply that across hundreds of change requests per quarter, and the time savings justify the learning investment within the first month. But speed is the least interesting benefit — the real value is in drift detection, peer review, and rollback capability.

How to Automate Cisco ACI with Terraform Technical Architecture

Imperative vs. Declarative: Why It Matters for ACI

The critical distinction between a Python script that pushes ACI config and Terraform is idempotency. A Python script that creates a tenant will fail or create a duplicate if you run it twice. Terraform checks the current state first — if the tenant already exists and matches your code, it does nothing. If someone manually changed the VRF name through the APIC GUI, terraform plan shows exactly what drifted and offers to fix it.

ApproachBehavior on Re-runDrift DetectionRollbackACI Use Case
Python + APIC REST APIFails or creates duplicatesNone — must build custom logicManual restore from backupOne-off scripts, quick prototyping
Ansible ACI ModulesIdempotent per taskLimited — task-level onlyRe-run previous playbookConfig pushes, compliance checks
Terraform ACI ProviderIdempotent by designBuilt-in via state comparisonterraform apply with previous codeFull lifecycle management, multi-env
Nexus-as-Code (NAC)Idempotent + YAML-drivenBuilt-in + schema validationgit revert + terraform applyEnterprise-scale ACI automation

For CCIE Automation candidates specifically, the exam blueprint section 2.0 covers Infrastructure as Code at 30% weight. Terraform with Cisco providers is explicitly listed alongside Ansible. Understanding both tools — and when to use which — is a tested skill.

How Does the Terraform ACI Provider Work?

The Cisco ACI Terraform provider (registry: CiscoDevNet/aci, version 2.x) translates HCL resource declarations into APIC REST API calls using the standard MO (Managed Object) model. According to HashiCorp’s official documentation, the provider supports 90+ resources and data sources covering tenants, networking, security policies, L4-L7 service graphs, and fabric access policies. Every HCL resource maps one-to-one to an ACI managed object class — aci_tenant maps to fvTenant, aci_vrf maps to fvCtx, aci_bridge_domain maps to fvBD.

Here is a minimal working example that provisions a production tenant with a VRF and bridge domain — the three objects you will create most frequently:

# providers.tf
terraform {
  required_providers {
    aci = {
      source  = "CiscoDevNet/aci"
      version = "~> 2.15"
    }
  }
}

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-Web"
  description = "Production web services tenant"
}

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"
}

Run terraform init to download the provider, terraform plan to see the three resources that will be created, and terraform apply to execute. The entire operation completes in under 10 seconds against a lab APIC.

Authentication Best Practices

Never hardcode APIC credentials in .tf files. Use environment variables:

export ACI_USERNAME=admin
export ACI_PASSWORD=$(vault kv get -field=password secret/apic)
export ACI_URL=https://apic1.lab.local

For production, integrate with HashiCorp Vault or your organization’s secrets manager. The provider reads ACI_USERNAME, ACI_PASSWORD, and ACI_URL environment variables automatically — no provider block credentials needed.

What Is Nexus-as-Code and Why Does It Change Everything?

Nexus-as-Code (NAC) is a Cisco-maintained open-source Terraform module (netascode/nac-aci/aci on the Terraform Registry) that abstracts the raw ACI provider into a YAML-driven data model. Instead of writing HCL resource blocks for every tenant, VRF, bridge domain, and EPG, you write plain YAML — and NAC’s 150+ sub-modules translate that YAML into the correct Terraform resources automatically. According to the Cisco Live BRKDCN-2673 session (2025), NAC reduces the barrier to entry for network engineers who know ACI but have never written infrastructure code.

Here is the same tenant, VRF, and bridge domain from above — written as NAC YAML instead of raw HCL:

# data/tenants.yaml
apic:
  tenants:
    - name: PROD-Web
      description: "Production web services tenant"
      vrfs:
        - name: PROD-VRF
          ip_data_plane_learning: enabled
      bridge_domains:
        - name: WEB-BD
          vrf: PROD-VRF
          arp_flood: false
          unicast_route: true
          subnets:
            - ip: 10.1.100.1/24
              public: true
              shared: false
      application_profiles:
        - name: Web-App
          endpoint_groups:
            - name: Web-EPG
              bridge_domain: WEB-BD
              physical_domains:
                - PHY-DOM

The main.tf is minimal — it loads the YAML and passes it to the NAC module:

module "aci" {
  source  = "netascode/nac-aci/aci"
  version = "0.9.3"

  yaml_directories = ["data"]
}

That is the entire Terraform configuration. NAC parses the YAML data model, creates the appropriate aci_rest_managed resources for every object, handles dependency ordering, and manages the relationship bindings between tenants, VRFs, bridge domains, and EPGs. For a network engineer who understands ACI concepts but is not a developer, this is the difference between a 2-week Terraform learning curve and a 2-hour one.

NAC Architecture: How YAML Becomes API Calls

Understanding the NAC module architecture helps when troubleshooting. According to Tl10K’s detailed architecture analysis, the flow works like this:

  1. Your YAML files define the desired ACI state in the data/ directory
  2. main.tf loads all YAML files into a model variable via the yaml_directories parameter
  3. nac-aci root module (aci_tenants.tf, aci_access_policies.tf, etc.) parses the model and routes objects to the correct sub-modules
  4. Sub-modules (terraform-aci-tenant, terraform-aci-vrf, etc.) contain the actual aci_rest_managed resource blocks that make APIC REST API calls
  5. Terraform state records what was deployed, enabling drift detection on subsequent runs

This layered architecture means you never interact with raw API calls or HCL resource blocks — you only modify YAML files. NAC handles the translation.

How Do You Handle Existing ACI Fabrics with Terraform?

Brownfield import is the single most critical step when adopting Terraform for an existing ACI deployment — and the one most commonly skipped, leading to duplicate object errors or worse, silent creation of conflicting configurations. According to the Cisco Live BRKOPS-2142 session (2025), the NAC brownfield import tool (nac-import) automates the process of reading your existing APIC configuration and generating both the YAML data model files and the Terraform state entries.

How to Automate Cisco ACI with Terraform Industry Impact

The Brownfield Import Workflow

  1. Clone the nac-import tool from GitHub
  2. Point it at your APIC: nac-import --url https://apic1.lab.local --username admin
  3. Review the generated YAMLnac-import reads every managed object and produces data model files matching the NAC schema
  4. Run terraform init and terraform plan — the plan should show zero changes if the import was complete
  5. Commit to Git — your existing ACI fabric is now under version control

Without this step, writing HCL for objects that already exist causes one of two outcomes: Terraform tries to create duplicates (which APIC rejects with a 400 error), or Terraform creates objects with slightly different attributes that conflict with the existing configuration. Either way, your first terraform apply fails or causes a production incident.

Manual Import for Selective Management

If you only want to manage specific tenants with Terraform (leaving others untouched), use standard terraform import:

# Import an existing tenant into Terraform state
terraform import aci_tenant.prod uni/tn-PROD-Web

# Import an existing VRF
terraform import aci_vrf.prod_vrf uni/tn-PROD-Web/ctx-PROD-VRF

# Verify — plan should show no changes for imported resources
terraform plan

This selective approach is common in organizations where some tenants are managed by automation teams and others are still provisioned manually through the APIC GUI.

How Do You Set Up Remote State for Team-Based ACI Automation?

Terraform state must never live on a single engineer’s laptop in a team environment. The state file (terraform.tfstate) is Terraform’s record of every managed object — without it, Terraform cannot detect drift or plan changes accurately. According to The Network DNA (2026), state locking is the feature that prevents two engineers from running terraform apply simultaneously and corrupting the ACI fabric.

BackendState LockingBest ForCost
HCP Terraform (Terraform Cloud)✅ Built-inTeams wanting managed runs + approval UIFree tier available
AWS S3 + DynamoDB✅ DynamoDB lockAWS-native environments~$1/month
Azure Blob Storage✅ Blob lease lockAzure-native environments~$1/month
GitLab Managed State✅ Built-inTeams already using GitLab CI/CDIncluded in GitLab

Here is an S3 backend configuration — the most common choice for network teams:

terraform {
  backend "s3" {
    bucket         = "aci-terraform-state"
    key            = "prod/aci/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Separate state files per environment (dev/staging/prod) and per ACI fabric. A terraform destroy on a development state file cannot affect production because they are completely isolated.

How Do You Build a CI/CD Pipeline for ACI Changes?

The ultimate operational improvement from Terraform is treating network changes like software deployments — with automated validation, mandatory peer review, and gated approval before anything touches the fabric. According to the Cisco Live BRKDCN-2607 session (2025), organizations running Terraform through CI/CD pipelines eliminate 80% of ACI misconfigurations caused by manual processes.

Here is a GitHub Actions pipeline for ACI changes:

# .github/workflows/aci-deploy.yml
name: ACI Terraform Pipeline

on:
  pull_request:
    paths: ['aci/**']
  push:
    branches: [main]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init -backend=false
      - run: terraform validate
      - run: terraform fmt -check -recursive

  plan:
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform plan -out=tfplan -no-color
      # Post plan output as PR comment for peer review
      - uses: actions/github-script@v7
        with:
          script: |
            const output = `#### Terraform Plan 📋
            \`\`\`
            ${process.env.PLAN_OUTPUT}
            \`\`\``;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform apply -auto-approve

The environment: production gate means a designated approver must click “Approve” in GitHub before the apply job runs. This is your change management process — automated, auditable, and enforced by the pipeline.

What Are the Common Pitfalls When Starting with Terraform for ACI?

Network engineers transitioning from CLI-based workflows to Terraform consistently hit the same set of issues. According to Tl10K’s design considerations series (2024), the top three mistakes are: skipping brownfield import, storing state locally, and managing all environments from a single state file. Here are the pitfalls and their fixes:

PitfallWhat HappensFix
Skip brownfield importterraform apply tries to create existing objects → 400 errors or duplicatesAlways run nac-import or terraform import first
Local state fileOther team members cannot safely run Terraform; lost laptop = lost stateConfigure remote backend with locking on day one
Single state for all environmentsA dev mistake can destroy production resourcesSeparate state files per environment and per fabric
Hardcoded credentials in .tfSecrets committed to Git → security incidentUse environment variables + Vault integration
No terraform plan reviewChanges applied without peer review → misconfigurationsEnforce plan-before-apply in CI/CD with manual gate
Monolithic main.tf2000-line file that nobody can review or maintainSplit into logical files: tenants.tf, access.tf, fabric.tf

Provider Version Pinning

Always pin your provider version with a constraint:

required_providers {
  aci = {
    source  = "CiscoDevNet/aci"
    version = "~> 2.15"
  }
}

The ~> operator allows patch updates (2.15.x) but blocks minor version bumps (2.16.0) that might change resource behavior. Provider updates have historically changed attribute names or default values — a floating version can break your terraform plan output unexpectedly.

How Does This Map to the CCIE Automation Exam?

The CCIE Automation certification (rebranded from DevNet Expert in February 2026) dedicates section 2.0 — Infrastructure as Code — at 30% weight, making it the largest single section on the 8-hour lab exam. According to SMENode Academy (2026), the lab tests Terraform with Cisco ACI as one of the primary IaC scenarios alongside Ansible. Candidates must demonstrate the ability to write, debug, and troubleshoot Terraform configurations under time pressure.

Specific exam tasks that map directly to the skills in this guide:

  • Write Terraform HCL to provision ACI tenants, VRFs, and application profiles
  • Troubleshoot failed plans by reading provider error messages and APIC API responses
  • Use terraform import to bring existing objects under management
  • Configure remote state and explain locking behavior
  • Integrate Terraform into a CI/CD pipeline with validation and approval gates

For lab preparation, build a practice environment with EVE-NG or Cisco CML running an ACI simulator. The free APIC simulator (available through Cisco DevNet Sandbox) supports all Terraform operations — you do not need physical hardware to practice.

Internal resources for your CCIE Automation journey:

Frequently Asked Questions

Do I Need Programming Experience to Use Terraform with Cisco ACI?

No. HCL is a declarative configuration language, not a general-purpose programming language — there are no loops, conditionals, or data structures to wrestle with for basic ACI automation. According to The Network DNA (2026), most network engineers become productive with Terraform within a few days. With Nexus-as-Code, you only write YAML — a format most engineers already use for Ansible inventories. Git fundamentals (commits, branches, pull requests) matter more than coding experience.

What Is the Difference Between Terraform and Ansible for ACI Automation?

Terraform manages the full lifecycle of ACI objects declaratively — it creates, updates, and destroys resources to match your code, tracking everything in state. Ansible is imperative and task-oriented — it executes playbooks that push configuration changes. In practice, teams use Terraform for day-0/day-1 provisioning (creating tenants, VRFs, EPGs) and Ansible for day-2 operations (updating QoS policies, pushing ACL changes across existing EPGs). Both tools are tested on the CCIE Automation exam.

What Is Nexus-as-Code and How Does It Simplify Terraform for ACI?

Nexus-as-Code is a Cisco-maintained Terraform module (netascode/nac-aci/aci) with 150+ sub-modules that translates plain YAML files into Terraform ACI resources. Instead of writing individual aci_tenant, aci_vrf, and aci_bridge_domain HCL blocks, you define your entire ACI fabric in YAML and NAC handles the rest. It also includes a brownfield import tool, defaults files for common settings, and schema validation for your YAML data model.

Is Terraform on the CCIE Automation Exam Blueprint?

Yes. Section 2.0 — Infrastructure as Code — covers 30% of the CCIE Automation (formerly DevNet Expert) lab exam according to Cisco’s official blueprint. Terraform with Cisco providers (ACI, IOS-XE, Meraki) is explicitly listed alongside Ansible. The exam tests your ability to write, debug, import, and troubleshoot Terraform configurations under the 8-hour lab time constraint.

How Do I Handle Existing ACI Configurations with Terraform?

Use the nac-import tool from GitHub for bulk brownfield import — it reads your entire APIC configuration and generates both YAML data files and Terraform state entries. For selective management of specific tenants, use standard terraform import commands. The critical rule: never write HCL for ACI objects that already exist without importing them into state first. Skipping this step causes duplicate object errors or conflicting configurations.


Ready to fast-track your CCIE journey? Contact us on Telegram @firstpasslab for a free assessment.