# Automating Cisco IOS-XE Interface Configuration with Ansible Loops

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_vars`
    
* Ansible loop to iterate through interfaces
    

## Topology

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1750746811208/e615a1d7-d930-4620-9f82-974c566eedd6.png align="center")

## 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:

```plaintext
# inventory/hosts
[ios-xe]
10.1.1.181
10.1.1.184
```

### Per-host variables:

📁 `host_vars/10.1.1.181.yml`

```yaml
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`

```yaml
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`:

```yaml
---
- 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

```plaintext
#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**

```plaintext
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**

```bash
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_cli` for Cisco IOS devices, and ensure SSH + privilege access is enabled.
    
* Store variables per device in `host_vars/` for modularity.
    
* Validate results with `show running-config` or collect configs using `ios_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!
