Automating Cisco IOS-XE Interface Configuration with Ansible Loops

Visit to see more: https://linktr.ee/nddnam
I am an enthusiastic Network Engineer with 7+ years of experience working on MPLS L3VPN Network projects, Cisco SDWAN Deployment, and Enterprise Networks.
I love to automate every daily task and think Dev-Ops as always. Thus, I am entering the DevNet world.
In this blog, I'll show how to use Ansible to automate interface configuration across multiple Cisco IOS-XE routers using a loop. This is especially useful for bulk interface provisioning and ensuring consistency across your edge routers.
Objective
Configure 2 WAN Edge routers (IOS-XE) with multiple interfaces (WAN + OSPF) using a single playbook, leveraging:
Grouped hosts in inventory
Per-host variables stored in
host_varsAnsible loop to iterate through interfaces
Topology

Project Layout
ansible/
├── cisco-config.yml # Main playbook
├── inventory/
│ └── hosts # Inventory file listing the IOS-XE devices
├── host_vars/
│ ├── 10.1.1.181.yml # Host-specific variables for router 10.1.1.181
│ └── 10.1.1.184.yml # Host-specific variables for router 10.1.1.184
Inventory Structure
We maintain a structured inventory and variable layout:
# inventory/hosts
[ios-xe]
10.1.1.181
10.1.1.184
Per-host variables:
📁 host_vars/10.1.1.181.yml
interfaces:
- { wan_interface: "GigabitEthernet1", wan_description: "WAN1", wan_ip: "192.168.1.1", wan_mask: "255.255.255.0" }
- { wan_interface: "GigabitEthernet2", wan_description: "OSPF-INTERFACE", wan_ip: "192.168.20.1", wan_mask: "255.255.255.0" }
📁 host_vars/10.1.1.184.yml
interfaces:
- { wan_interface: "GigabitEthernet1", wan_description: "WAN1", wan_ip: "192.168.2.1", wan_mask: "255.255.255.0" }
- { wan_interface: "GigabitEthernet2", wan_description: "OSPF-INTERFACE", wan_ip: "192.168.20.2", wan_mask: "255.255.255.0" }
The Ansible Playbook
cisco-config.yml:
---
- name: Configure 2 WAN Edges connected and OSPF
hosts: ios-xe
gather_facts: no
connection: network_cli
tasks:
- name: Interface Configurations
cisco.ios.ios_config:
lines:
- description {{ item.wan_description }}
- no shutdown
- ip address {{ item.wan_ip }} {{ item.wan_mask }}
parents: interface {{ item.wan_interface }}
loop: "{{ interfaces }}"
Run the Playbook
#ansible-playbook -i inventory/hosts cisco-config.yml
Output Highlights
PLAY RECAP *********************************************************************
10.1.1.181 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.1.1.184 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Each router receives the interface configuration defined in its own host_vars YAML file.
Running configuration of 10.1.1.181
interface GigabitEthernet1
description WAN1
ip address 192.168.1.1 255.255.255.0
negotiation auto
!
interface GigabitEthernet2
description OSPF-INTERFACE
ip address 192.168.20.1 255.255.255.0
negotiation auto
!
Running configuration of 10.1.1.184
interface GigabitEthernet1
description WAN1
ip address 192.168.1.1 255.255.255.0
negotiation auto
!
interface GigabitEthernet2
description OSPF-INTERFACE
ip address 192.168.20.1 255.255.255.0
negotiation auto
!
This is achieved through a loop, ensuring scalability and flexibility when configuring multiple routers or interfaces.
Tips
Use
network_clifor Cisco IOS devices, and ensure SSH + privilege access is enabled.Store variables per device in
host_vars/for modularity.Validate results with
show running-configor collect configs usingios_command.
Feel free to clone, adapt, and expand this example to suit your network automation workflows. Automation doesn't have to be complex — start small, and grow from there!

![[SR-MPLS] LAB Segment Routing with SR-TE and PCE](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1746671465429%2F97233c37-df08-47a4-9148-0ccdc7b49622.png&w=3840&q=75)
![[SR-MPLS] IGP & SR-TE Segment Routing - Traffic Engineering](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1746670805015%2F8e6879c4-0dbd-4513-9327-9026de08933f.png&w=3840&q=75)

