First Steps
This section provides a simple example of configuring Cisco NX-OS switches using Network-as-Code. It walks through a VXLAN EVPN fabric deployment to get familiar with the NX-OS NAC module and the YAML-driven approach.
The repository used in this example can be found at: https://github.com/netascode/nac-nxos-vxlan-example
This example assumes you have installed the following prerequisites.
- Terraform 1.9.0 or later.
- Git
- Your preferred text editor / Integrated Development Environment (IDE) (such as VisualStudio Code)
Step 1: Enable NX-API on Devices
Section titled “Step 1: Enable NX-API on Devices”NX-API must be enabled on each NX-OS device before Terraform can communicate with it. SSH into each device and run:
feature nxapiEnsure the device management IP is reachable from the machine running Terraform.
Step 2: Set Environment Variables
Section titled “Step 2: Set Environment Variables”The NX-OS provider authenticates using environment variables:
export NXOS_USERNAME=adminexport NXOS_PASSWORD=passwordStep 3: Clone the Repository
Section titled “Step 3: Clone the Repository”git clone https://github.com/netascode/nac-nxos-vxlan-example.gitcd nac-nxos-vxlan-exampleOpen the folder in your preferred editor / IDE.
Step 4: Understand the Module Configuration
Section titled “Step 4: Understand the Module Configuration”The main.tf file contains the required providers and points to the YAML data and template directories:
terraform { required_providers { nxos = { source = "CiscoDevNet/nxos" } }}
module "nxos" { source = "netascode/nac-nxos/nxos" version = "0.3.0"
yaml_directories = ["data/"] template_directories = ["templates/"]}The required_providers block specifies the NX-OS provider from CiscoDevNet. Authentication is handled via the environment variables set in Step 2. The module block points to the NAC NX-OS module, reads all YAML files from the data/ directory, and loads template files from the templates/ directory. Device URLs are defined in the YAML inventory, so no explicit provider block with a URL is needed.
Step 5: Explore the Data Model
Section titled “Step 5: Explore the Data Model”The data/ directory contains YAML files that describe the desired state of the fabric, and the templates/ directory contains reusable configuration templates. Here are the key concepts:
Inventory
Section titled “Inventory”The inventory.nac.yaml file defines global variables, device groups, and devices with their management URLs and per-device variables:
nxos: global: variables: bgp_asn: 65000 anycast_rp_ip: 10.254.254.1 anycast_gw_mac: 00:00:22:22:33:33
device_groups: - name: FABRIC templates: - global - underlay_ip - underlay_ospf - underlay_multicast - overlay_bgp - name: LEAFS templates: - overlay_vxlan - name: SPINES
devices: - name: LEAF1 url: https://10.1.1.1 device_groups: - FABRIC - LEAFS variables: mgmt_ip: 10.1.1.1 leaf_id: 1
- name: SPINE1 url: https://10.1.1.3 device_groups: - FABRIC - SPINES variables: mgmt_ip: 10.1.1.3 spine_id: 1Global variables (like bgp_asn) are shared across all devices. Device groups assign templates to sets of devices — for example, all devices in the FABRIC group receive the underlay and overlay templates. Per-device variables (like leaf_id) allow templates to generate unique configurations per device.
Update the device URLs to match your environment.
Device Groups and Services
Section titled “Device Groups and Services”Device groups allow you to logically group devices and assign shared templates and variables. They are also used to define services. For example, service_prod_web.nac.yaml defines a Layer 2 service across two leaf switches:
nxos: device_groups: - name: SERVICE_PROD_WEB devices: - LEAF1 - LEAF2 templates: [service_l2] variables: vlan_id: 1001 vlan_name: PROD_WEBThis assigns the service_l2 template to both LEAF1 and LEAF2 with the specified variables. Adding more services is as simple as creating additional YAML files with different device groups and variables.
Templates
Section titled “Templates”Templates are external .yaml.tftpl files that generate data model configuration using Terraform template syntax. They support variable substitution and have access to the full inventory via the GLOBAL object. Templates are registered in templates.nac.yaml:
nxos: templates: - name: global type: file file: templates/global.yaml.tftpl
- name: underlay_ospf type: file file: templates/underlay_ospf.yaml.tftpl
- name: service_l2 type: file file: templates/service_l2.yaml.tftplA template file uses variables from the device and global scope, and can iterate over the inventory to discover peers. For example, the service_l2 template generates VLAN, NVE VNI, and EVPN configuration from just two variables:
vlan: vlans: - id: ${vlan_id} vn_segment: ${try(vni, try(l2vni_base, 30000) + vlan_id)} name: ${vlan_name}interfaces: nve: vnis: - vni: ${try(vni, try(l2vni_base, 30000) + vlan_id)}evpn: vnis: - vni: ${try(vni, try(l2vni_base, 30000) + vlan_id)} rd: auto route_target_both_auto: trueVariables like ${vlan_id} are resolved per device from the variables defined in the device group. The GLOBAL object provides access to the full inventory, enabling templates to discover spine or leaf peers dynamically for BGP neighbor or interface configuration.
Step 6: Deploy the Configuration
Section titled “Step 6: Deploy the Configuration”Initialize Terraform to download all required providers and modules:
terraform initPreview the changes:
terraform planApply the configuration to push changes to the NX-OS devices:
terraform applyType yes to approve.
Step 7: Verify on Device
Section titled “Step 7: Verify on Device”SSH into the NX-OS devices and verify that the configuration was applied:
show running-config | include hostnameshow vlan briefshow ip bgp summaryshow nve peersStep 8: Cleaning Up
Section titled “Step 8: Cleaning Up”Run terraform destroy to remove all configuration managed by Terraform:
terraform destroyType yes to approve. Verify on the devices that the configuration has been reverted.