Back to Blog
CCIE Security22 min read

ACI Infrastructure as Code with Terraform | NHPREP

A
Admin
March 26, 2026
ACI TerraformACI IaCTerraform ACI providerdata center automationinfrastructure as code

ACI Infrastructure as Code with Terraform

Introduction

Imagine managing hundreds of tenants, bridge domains, EPGs, and contracts across multiple ACI fabrics — all by clicking through the APIC GUI one object at a time. Every change is manual, every rollback is painful, and every audit requires painstaking screen-by-screen verification. Now imagine replacing all of that with a single declarative configuration file that describes your entire intended network state and applies it in seconds. That is the promise of ACI Terraform automation, and it is transforming how network engineers operate data center fabrics.

Infrastructure as Code (IaC) has already reshaped how servers, storage, and cloud resources are provisioned. The same principles — version control, repeatability, idempotency, and peer review — apply directly to network infrastructure. When you combine Terraform, the industry-leading open-source IaC tool from HashiCorp, with the Cisco ACI provider maintained by DevNet, you get a powerful pipeline for managing your ACI fabric programmatically.

In this article, we will take a deep dive into ACI Infrastructure as Code with Terraform. You will learn what Terraform is and how its architecture works, how the ACI and MSO providers connect to your fabric, how to structure a Terraform project for ACI, and how to walk through the full init-plan-apply-destroy lifecycle. Whether you are a network engineer exploring automation for the first time or a DevOps practitioner extending your IaC skills into data center networking, this guide will give you the foundational knowledge you need to get started.

What Is Terraform and Why Does It Matter for ACI?

Terraform is an open-source infrastructure provisioning tool created by HashiCorp. It is written in Golang and distributed as a single binary, which makes installation straightforward on virtually any platform — Linux, macOS, or Windows. Unlike imperative scripting approaches where you write step-by-step instructions telling the system how to reach a desired state, Terraform is declarative. You describe what you want the infrastructure to look like, and Terraform figures out how to get there.

The configuration language used by Terraform is called HashiCorp Configuration Language (HCL). HCL is purpose-built for infrastructure definitions. It is human-readable, supports variables and expressions, and strikes a balance between the simplicity of YAML and the power of a full programming language. For ACI engineers, this means you can describe your tenants, VRFs, bridge domains, application profiles, EPGs, contracts, and access policies in clean, readable text files that can be stored in Git, reviewed by peers, and applied consistently across environments.

One of Terraform's most significant strengths is its multi-cloud support. The same tool and the same workflow that provisions AWS EC2 instances or Azure virtual networks can also configure your on-premises ACI fabric. This unified approach is especially valuable in hybrid environments where data center workloads span both physical ACI fabrics and public cloud sites managed through Nexus Dashboard Orchestrator.

Declarative vs. Imperative: Why It Matters

In a traditional imperative approach — whether using Python scripts, Ansible playbooks executed in a procedural manner, or manual CLI commands — you must carefully sequence every operation. Creating a tenant before a VRF, a VRF before a bridge domain, a bridge domain before an EPG. If something fails midway, you are responsible for understanding the partial state and recovering from it.

With Terraform's declarative model, you simply declare the full desired state. Terraform builds an internal dependency graph, determines the correct order of operations, and handles creation, modification, and deletion automatically. If a resource already exists and matches the desired state, Terraform leaves it untouched. If it has drifted, Terraform corrects it. This idempotent behavior is critical for maintaining consistency across large-scale ACI deployments.

How Does Terraform Architecture Work?

Understanding Terraform's internal architecture is essential before you begin writing configurations for ACI. The architecture consists of two primary components: Terraform Core and Terraform Providers.

Terraform Core

Terraform Core is the engine that reads your HCL configuration files, builds the dependency graph, compares the desired state against the current state, and generates an execution plan. It is provider-agnostic — the core engine itself knows nothing about ACI, AWS, Azure, or any other platform. Its job is purely to orchestrate the lifecycle of resources defined in your configuration.

When you run commands like terraform plan or terraform apply, it is Terraform Core that parses your .tf files, resolves variable references, evaluates expressions, and determines which resources need to be created, updated, or destroyed.

Terraform Providers

Providers are the plugins that give Terraform the ability to communicate with specific infrastructure platforms. Each provider implements the logic to translate Terraform resource definitions into API calls against the target system. For ACI, the provider communicates with the APIC controller via its REST API to perform CRUD operations — Create, Read, Update, and Delete — on managed objects.

The relationship is straightforward:

ComponentRole
Terraform CoreReads HCL, builds dependency graph, generates execution plan
Terraform ProvidersTranslate resource definitions into platform-specific API calls
Infrastructure (ACI)Receives API calls and applies configuration changes

This separation of concerns is what gives Terraform its extensibility. The same core engine works identically whether the provider is targeting AWS, Azure, or ACI. The provider handles all platform-specific logic, authentication, and API interaction.

Understanding the Terraform ACI Provider

The Terraform ACI provider is the bridge between your HCL configuration files and your ACI fabric. It is important to note that the ACI provider is not maintained by HashiCorp — it is developed and maintained by DevNet. This means that updates, bug fixes, and new resource support follow the DevNet release cycle rather than the HashiCorp provider release schedule.

Scale and Coverage

The ACI provider is a mature and comprehensive plugin. It offers over 250 resources and data sources for ACI, covering the vast majority of objects you would configure through the APIC GUI or API. This includes tenants, VRFs, bridge domains, application profiles, EPGs, contracts, filters, L3Outs, access policies, interface policies, switch profiles, and much more.

For multi-site deployments managed through Nexus Dashboard Orchestrator (NDO), there is a separate MSO provider that offers 45+ resources and data sources. This allows you to manage schemas, templates, and site-level configurations programmatically alongside your per-fabric ACI configurations.

ProviderMaintained ByResources & Data SourcesTarget
ACIDevNet250+Single-fabric APIC
MSO/NDODevNet45+Multi-site NDO

Authentication Methods

Each Terraform provider has its own authentication mechanism. The ACI and MSO providers differ in how they authenticate:

  • ACI Provider: Uses signature/certificate-based authentication. You generate a certificate, upload the public key to an APIC user account, and configure Terraform with the private key. This avoids storing passwords in plain text and provides a more secure, token-free authentication flow.
  • MSO Provider: Uses username/password authentication against the Nexus Dashboard Orchestrator.

Pro Tip: Certificate-based authentication for the ACI provider is strongly recommended for production environments. It eliminates the need to store or rotate passwords in your Terraform variable files and aligns with security best practices for automated pipelines.

What Are Terraform Resources and Data Sources?

Two fundamental concepts in Terraform are resources and data sources. Understanding the difference between them is critical for writing effective ACI configurations.

Resources

A resource is a Terraform object that manages an infrastructure element. When you define a resource in your HCL configuration, Terraform takes responsibility for the full lifecycle of that object — creating it if it does not exist, updating it if its attributes have changed, and destroying it when it is removed from the configuration.

Every resource definition has two identifiers: the resource type (which corresponds to the ACI object class, like aci_tenant or aci_bridge_domain) and the resource name (a label you choose to reference that specific instance within your Terraform configuration).

Resource attributes fall into three categories:

Attribute TypeDescription
RequiredMust be specified in your configuration. The resource cannot be created without it.
OptionalCan be specified but has a default value if omitted.
ComputedDetermined by the infrastructure after creation. You cannot set it — Terraform reads it from the API response.

For example, when defining a tenant resource, the tenant name is a required attribute. The description might be optional. The distinguished name (DN) assigned by APIC would be a computed attribute that Terraform reads back after creation.

Data Sources

A data source reads data from an existing infrastructure element without managing it. This is useful when you need to reference objects that were created outside of Terraform — perhaps manually through the GUI or by another automation tool. Data sources allow you to query the ACI fabric for existing objects and use their attributes in your own resource definitions without Terraform attempting to manage their lifecycle.

The distinction is important: resources are read-write, data sources are read-only. Use resources for objects Terraform should own, and data sources for objects Terraform should reference but not modify.

How Do Terraform Variables Make ACI Projects Dynamic?

Hardcoding values like tenant names, VLAN IDs, IP addresses, and descriptions directly into your resource definitions works for small-scale testing, but it does not scale. Terraform variables solve this problem by enabling parameterized configuration and a clean separation between data and logic.

Variable Declaration

Variables are declared in .tf files — typically in a dedicated variables.tf file to keep your project organized. A variable declaration specifies the variable name, its type (string, number, bool, list, map, etc.), an optional description, and an optional default value.

Value Assignment

Variable values can be provided through multiple mechanisms:

  1. .tfvars files — Dedicated variable value files (e.g., terraform.tfvars or production.tfvars) that contain key-value pairs.
  2. Command-line flags — Passing values directly with the -var flag when running terraform plan or terraform apply.
  3. Environment variables — Setting TF_VAR_<name> environment variables in your shell.

This separation is powerful for ACI deployments because it allows you to maintain a single set of logic files (your resource definitions in main.tf, tenant.tf, access_policies.tf, etc.) while swapping out different variable files for different environments. The same Terraform code that configures your lab ACI fabric can configure your production fabric — only the variable values change.

Pro Tip: Store your .tf logic files in version control and keep sensitive .tfvars files (containing passwords or certificates) out of your repository using .gitignore. This ensures your infrastructure logic is versioned and reviewable while credentials remain protected.

Structuring a Terraform Project for ACI

A Terraform project is a collection of HCL instructions that declare the intended state of your infrastructure. These instructions are written in .tf files within a working directory. When you run Terraform commands, the tool scans the entire working directory and processes all .tf files it finds.

Splitting Configuration Across Files

A key best practice is to split your configuration across multiple .tf files organized by function. While Terraform treats all .tf files in a directory as a single configuration, splitting them improves readability and maintainability. A well-structured ACI Terraform project might look like this:

FilePurpose
main.tfProvider configuration, backend settings
variables.tfVariable declarations
terraform.tfvarsVariable value assignments
access_policies.tfVLAN pools, domains, AEPs, interface policies
fabric_policies.tfFabric-wide settings, NTP, DNS, SNMP
tenant.tfTenants, VRFs, BDs, AP, EPGs, contracts

This structure mirrors the logical sections of the APIC GUI and makes it easy for network engineers to find and modify specific parts of the configuration. A colleague looking for access policy definitions knows to open access_policies.tf. Someone troubleshooting tenant configuration goes straight to tenant.tf.

Why File Organization Matters

When you are managing a single tenant with a few EPGs, file organization is a convenience. When you are managing an entire data center fabric with dozens of tenants, hundreds of EPGs, complex contract relationships, and detailed access policies, it becomes a necessity. Proper file organization reduces merge conflicts in version control, makes code reviews efficient, and helps new team members understand the project structure quickly.

The Terraform Workflow: Init, Plan, Apply, Destroy

The core Terraform workflow consists of four commands that take you from a fresh project to a fully provisioned infrastructure — and back again if needed. Each command serves a specific purpose in the lifecycle, and understanding them is essential for working with ACI Terraform automation.

terraform init

The terraform init command initializes your Terraform project. Its primary function is to download provider plugins specified in your configuration. When you declare the ACI provider in your main.tf, running terraform init fetches the appropriate version of the provider binary from the Terraform registry and stores it locally.

terraform init

This command must be run before any other Terraform command in a new project or whenever you change provider versions. It also initializes the backend configuration if you are using remote state storage.

The init process creates a .terraform directory in your project folder containing the downloaded provider plugins and a .terraform.lock.hcl file that records the exact provider versions used. This lock file should be committed to version control to ensure all team members use identical provider versions.

terraform plan

The terraform plan command is your dry run. It reads your HCL configuration, queries the current state of the infrastructure (either from the state file or by communicating with the ACI fabric), and determines what actions are required to achieve the desired state.

terraform plan

The plan output shows you exactly what Terraform intends to do: which resources will be created, which will be modified, and which will be destroyed. Resources marked for creation appear with a + symbol, modifications with a ~, and deletions with a -.

This dry-run capability is invaluable in production ACI environments. Before making any changes to your fabric, you can review the plan output to verify that Terraform will do exactly what you expect — and nothing more. Unexpected changes in the plan output often indicate configuration drift that should be investigated before applying.

Pro Tip: Always run terraform plan before terraform apply, especially in production environments. Review the plan output carefully. If Terraform plans to destroy and recreate a resource you expected to merely update, investigate the cause before proceeding. In an ACI fabric, an unintended EPG deletion could cause a network outage.

terraform apply

The terraform apply command takes the execution plan and applies the configuration to the infrastructure. For ACI, this means Terraform sends REST API calls to the APIC controller to create, modify, or delete managed objects according to the plan.

terraform apply

By default, terraform apply generates a new plan and asks for confirmation before proceeding. You can skip the confirmation prompt by passing the -auto-approve flag, but this is generally discouraged in production environments where human review of changes is a safety net.

After successful application, Terraform updates the state file to reflect the new state of the infrastructure. This state file becomes the source of truth for subsequent plan and apply operations.

terraform destroy

The terraform destroy command is the reverse of apply. It destroys all infrastructure managed by Terraform in the current project. Every resource tracked in the state file is deleted from the ACI fabric.

terraform destroy

This command is extremely useful in lab and development environments where you want to tear down an entire configuration and start fresh. In production, it should be used with extreme caution — or not at all. The -target flag can be used to destroy specific resources rather than everything.

The Complete Lifecycle

The four commands form a complete lifecycle:

StepCommandAction
1terraform initDownload providers, initialize project
2terraform planDry run — show what will change
3terraform applyExecute changes against ACI fabric
4terraform destroyRemove all managed infrastructure

In practice, the daily workflow is typically a loop of editing .tf files, running plan to verify changes, and running apply to implement them. The init step is only needed at project setup or when changing providers, and destroy is reserved for teardown scenarios.

How Does the Terraform State File Work with ACI?

The Terraform state file is one of the most critical and often misunderstood components of a Terraform project. It is the mechanism by which Terraform tracks the relationship between your HCL configuration and the real-world infrastructure objects in your ACI fabric.

What the State File Contains

The state file stores information about every resource managed by Terraform. For each resource, it records the resource type, the resource name, the current attribute values (as last known by Terraform), and the unique identifier used to reference the object in the infrastructure — in ACI's case, the distinguished name (DN).

When you run terraform plan, Terraform compares the desired state (from your .tf files) against the last known state (from the state file). If they differ, Terraform generates a plan to reconcile the difference.

Terraform as a Resource Manager

The state file effectively turns Terraform into a resource manager for your ACI fabric. It knows which objects it created, which attributes those objects have, and how they relate to one another. This tracking capability is what enables Terraform to:

  • Detect drift: If someone manually modifies an object in APIC that Terraform manages, the next terraform plan will detect the difference and propose correcting it.
  • Handle dependencies: Terraform knows that an EPG depends on an application profile, which depends on a tenant. If you remove a tenant from your configuration, Terraform automatically plans the deletion of all dependent objects in the correct order.
  • Enable selective updates: When you change a single attribute of one resource, Terraform only modifies that specific object rather than reapplying the entire configuration.

State File Best Practices

The state file is stored locally by default as terraform.tfstate in your project directory. For team environments, this presents challenges — multiple engineers cannot safely run Terraform simultaneously against the same state file without risking corruption or conflicts.

Pro Tip: For team-based ACI automation projects, consider using a remote state backend with state locking. This ensures that only one person can run terraform apply at a time, preventing conflicting changes to your ACI fabric.

Setting Up the ACI Terraform Lab Environment

A proper lab environment is essential for learning and testing ACI Terraform automation before applying it to production fabrics. A representative lab setup includes the following components:

Required Components

ComponentDescription
ACI SimulatorA simulated ACI fabric running APIC software (e.g., version 5.2(7f)) for safe testing
Nexus Dashboard OrchestratorNDO (e.g., version 4.1(1i)) for multi-site automation scenarios
Code EditorVisual Studio Code with HCL/Terraform extensions for syntax highlighting
Terraform RuntimeA Linux environment (e.g., Windows Subsystem for Linux) with Terraform installed

The ACI Simulator provides a fully functional APIC API without requiring physical hardware. This allows you to run terraform apply and terraform destroy repeatedly without any risk to production networks. You can experiment with different configuration structures, test error handling, and build confidence in your Terraform workflows.

For multi-site scenarios, having two ACI simulators representing different sites (for example, a "San Francisco" site and a "New York" site) managed through a single NDO instance allows you to practice with the MSO provider alongside the ACI provider.

Getting Started in the Lab

The typical workflow for setting up a new ACI Terraform lab project is:

  1. Create a project directory and initialize it with terraform init after defining your provider configuration.
  2. Configure the ACI provider with the APIC URL and certificate-based authentication credentials.
  3. Start with a simple resource — a single tenant — and run the full init, plan, apply cycle.
  4. Incrementally add VRFs, bridge domains, application profiles, and EPGs.
  5. Practice modifying and destroying resources to observe Terraform's behavior.
  6. Introduce variables to parameterize your configuration.
  7. Split your growing configuration across multiple .tf files.

This incremental approach builds understanding of Terraform concepts one layer at a time, rather than overwhelming you with a complex multi-tenant configuration from the start.

Best Practices for ACI Infrastructure as Code with Terraform

Adopting Terraform for ACI management is not just about learning the tool — it is about establishing practices that make your automation reliable, maintainable, and safe for production use.

Version Control Everything

Every .tf file in your project should be stored in a Git repository. This gives you a complete history of every change made to your ACI fabric configuration, the ability to review changes before they are applied through pull requests, and the power to roll back to any previous state if a change causes problems.

Use Consistent Naming Conventions

ACI objects have naming constraints, and your Terraform resource names should follow a consistent convention. Establish naming patterns for tenants, VRFs, bridge domains, and EPGs that make their purpose immediately clear from the name alone.

Separate Environments with Variable Files

Maintain separate .tfvars files for each environment — lab, staging, and production. The same .tf logic files apply across all environments; only the variable values change. This ensures that your production configuration is tested in lower environments before deployment.

Plan Before Apply, Always

Never run terraform apply without first reviewing the output of terraform plan. In an ACI fabric, an unexpected change could affect network connectivity for production workloads. The plan output is your safety net — use it.

Manage State Carefully

The state file is the single source of truth for Terraform. Back it up regularly. If you are working in a team, use remote state with locking to prevent concurrent modifications. Never manually edit the state file unless you fully understand the consequences.

Start Small, Scale Gradually

Begin with a single tenant and a few objects. Once you are comfortable with the workflow, expand to access policies, fabric policies, and multi-site configurations. Trying to automate an entire production fabric on day one is a recipe for frustration and errors.

Pro Tip: Treat your Terraform project structure like your ACI fabric structure. If you organize your APIC configuration logically by tenant, by function, by site, mirror that same organization in your .tf file layout. This makes navigation intuitive for every network engineer on your team.

ACI Terraform Provider vs. Other Automation Approaches

Terraform is not the only way to automate ACI. Understanding where it fits relative to other approaches helps you choose the right tool for each use case.

ApproachStyleState TrackingACI SupportBest For
TerraformDeclarativeYes (state file)250+ resources via providerFull lifecycle management
REST API (Python)ImperativeNo (manual)Full APIC APICustom integrations, one-off scripts
AnsibleDeclarative/ImperativeLimitedACI collectionConfiguration management, playbooks

Terraform's primary advantage is its state tracking. Because it maintains a state file, it can detect drift, manage dependencies, and perform intelligent updates. REST API scripts and Ansible playbooks typically do not maintain state between runs, which means they cannot easily detect when the real infrastructure has diverged from the intended configuration.

The Terraform ACI provider's 250+ resources and data sources cover the vast majority of ACI use cases. Combined with the 45+ resources in the MSO/NDO provider, you can manage both single-fabric and multi-site deployments from a unified IaC workflow.

Frequently Asked Questions

What is the difference between the ACI provider and the MSO provider in Terraform?

The ACI provider communicates directly with a single APIC controller to manage objects within one ACI fabric. It supports over 250 resources and data sources covering tenants, networking, security, access policies, and fabric policies. The MSO provider, on the other hand, communicates with Nexus Dashboard Orchestrator to manage multi-site configurations. It supports 45+ resources and data sources for schemas, templates, and cross-site policies. If you are managing a single fabric, you use the ACI provider. If you are managing multiple fabrics through NDO, you use the MSO provider — or both together.

How does Terraform authenticate to the ACI fabric?

The ACI provider uses signature/certificate-based authentication. You generate an X.509 certificate, upload the public key to a local user account on APIC, and configure the Terraform provider with the private key path. Terraform then signs each API request using the private key. This is more secure than username/password authentication because no credentials are transmitted over the network. The MSO provider uses a different approach, authenticating with a username and password against the NDO login API.

Can Terraform detect manual changes made to my ACI fabric?

Yes. Terraform maintains a state file that records the last known state of every managed resource. When you run terraform plan, Terraform queries the ACI fabric via the APIC REST API and compares the actual state against the recorded state. If someone has manually modified or deleted a Terraform-managed object through the APIC GUI, the plan output will show the discrepancy and propose changes to bring the fabric back in line with the declared configuration. This drift detection is one of Terraform's most powerful features for maintaining consistency.

Is it safe to use terraform destroy in a production ACI environment?

The terraform destroy command removes all infrastructure managed by the current Terraform project. In a production environment, this could delete tenants, VRFs, bridge domains, EPGs, contracts, and access policies — causing a complete network outage for affected workloads. It should only be used in lab or development environments for teardown and rebuild scenarios. If you need to remove specific resources in production, remove them from your .tf configuration files and run terraform apply instead, which will selectively delete only those resources.

Do I need programming experience to use Terraform with ACI?

No. Terraform's HashiCorp Configuration Language (HCL) is a declarative configuration language, not a general-purpose programming language. If you can read and write structured text files — similar to JSON or YAML — you can learn HCL. The syntax is straightforward: you declare resources with a type and name, set attributes as key-value pairs, and reference variables where needed. Network engineers who are comfortable with ACI concepts (tenants, VRFs, BDs, EPGs) can become productive with Terraform relatively quickly.

What version of ACI is compatible with the Terraform provider?

The Terraform ACI provider communicates with the APIC through its REST API, which has been available across many ACI software versions. Lab environments commonly use ACI Simulator running versions such as 5.2(7f). For production compatibility, always check the provider documentation for the specific version you intend to use, as newer provider releases may add support for features introduced in recent ACI software versions.

Conclusion

ACI Infrastructure as Code with Terraform represents a fundamental shift in how network engineers manage data center fabrics. By moving from manual, GUI-driven configuration to declarative, version-controlled HCL files, you gain repeatability, auditability, and the ability to manage complex ACI environments at scale.

The key takeaways from this guide are:

  • Terraform is an open-source, declarative IaC tool written in Golang that uses HCL for configuration.
  • The architecture separates Terraform Core (orchestration engine) from Providers (platform-specific API integration).
  • The ACI provider, maintained by DevNet, offers 250+ resources and uses certificate-based authentication, while the MSO provider offers 45+ resources with username/password authentication.
  • Resources manage infrastructure objects through full CRUD lifecycle; data sources read existing objects without managing them.
  • Variables enable parameterized, reusable configurations with separation of data and logic.
  • The four core commandsterraform init, terraform plan, terraform apply, and terraform destroy — form the complete operational workflow.
  • The state file is Terraform's mechanism for tracking managed infrastructure, detecting drift, and enabling intelligent updates.

Whether you are automating a lab fabric for certification study or preparing to roll out IaC practices across a production data center, Terraform provides a proven, scalable approach to ACI automation. Start with a single tenant in a simulator environment, master the workflow, and build from there.

To continue building your automation and data center skills, explore the certification preparation courses available at nhprep.com for hands-on training across networking, security, and cloud technologies.