Ansible is an agentless automation tool that connects to network devices over SSH (or NETCONF) and executes tasks defined in YAML files called playbooks. Unlike Python scripts using Netmiko or NAPALM, Ansible does not require any code on the managed device — it uses the device's existing SSH management plane. Playbooks describe the desired state of configuration rather than a list of imperative commands, making them repeatable and idempotent by design. The cisco.ios Ansible collection provides purpose-built modules for Cisco IOS and IOS-XE that understand the platform's configuration syntax natively.
Ansible vs Python for Network Automation
Before choosing Ansible, it's worth understanding where it sits relative to other tools. Python libraries like Netmiko provide SSH transport for sending raw CLI commands. NAPALM adds a multi-vendor abstraction layer and getter methods. Ansible sits a level above — it orchestrates tasks, manages state, and integrates with your wider infrastructure tooling (CI/CD, secrets managers, ticketing systems).
| Tool | Approach | Learning Curve | Idempotent | Best For |
|---|---|---|---|---|
| Ansible (cisco.ios) | YAML playbooks, declarative | Low–Medium | Yes (most modules) | Config management, bulk changes, multi-team environments |
| Python + Netmiko | SSH scripts, imperative | Medium | No (manual logic required) | Custom parsing, one-off scripts, complex logic |
| n8n workflows | Visual node-based flows | Low | Depends on design | Event-driven triggers, alert workflows, API integrations |
How to Automate Cisco IOS with Ansible — 6 Steps
cisco.ios collection. The collection provides all IOS-specific modules and connection plugins needed for Cisco automation.network_cli with ansible_network_os: cisco.ios.ios.cisco.ios.ios_facts to pull structured data from your devices — hostname, interfaces, VLANs, ARP table. This validates your inventory and connectivity before attempting any changes.cisco.ios.ios_config module takes a list of config lines and pushes them to devices. Use the src parameter to push a full config template rendered with Jinja2 variables per device.ansible-playbook --check to preview changes without applying them. Use block and rescue sections to handle unreachable devices gracefully and send alerts on failure.0 2 * * * /usr/local/bin/ansible-playbook backup.yml), or trigger it from an n8n HTTP Request node for event-driven execution on config change alerts.Inventory File Example
Below is a working INI-format inventory for a typical three-tier Cisco estate. Store credentials in Ansible Vault, not in plain text.
[core_switches]
core-sw-01 ansible_host=10.0.1.1
core-sw-02 ansible_host=10.0.1.2
[distribution_switches]
dist-sw-01 ansible_host=10.0.2.1
dist-sw-02 ansible_host=10.0.2.2
[access_switches]
access-sw-01 ansible_host=10.0.3.1
access-sw-02 ansible_host=10.0.3.2
access-sw-03 ansible_host=10.0.3.3
[cisco_ios:children]
core_switches
distribution_switches
access_switches
[cisco_ios:vars]
ansible_network_os=cisco.ios.ios
ansible_connection=network_cli
ansible_user=netadmin
ansible_password={{ vault_ssh_password }}
ansible_become=yes
ansible_become_method=enable
ansible_become_password={{ vault_enable_password }}
Backup Playbook — Full Example
This playbook connects to all Cisco IOS devices, runs show running-config, and saves the output to a timestamped file per device. It's a solid first automation to run in production.
---
- name: Backup Cisco IOS running configurations
hosts: cisco_ios
gather_facts: false
vars:
backup_dir: "/opt/network-backups/{{ ansible_date_time.date }}"
tasks:
- name: Create backup directory
file:
path: "{{ backup_dir }}"
state: directory
mode: '0755'
delegate_to: localhost
run_once: true
- name: Collect running configuration
cisco.ios.ios_command:
commands:
- show running-config
register: config_output
- name: Save config to file
copy:
content: "{{ config_output.stdout[0] }}"
dest: "{{ backup_dir }}/{{ inventory_hostname }}_running-config.txt"
delegate_to: localhost
- name: Log backup completion
debug:
msg: "Backup complete for {{ inventory_hostname }} — saved to {{ backup_dir }}"
ios_config Task Example
Use ios_config to push configuration changes. The module tracks what has changed and only applies lines not already present in the running config.
- name: Apply NTP and logging baseline
cisco.ios.ios_config:
lines:
- ntp server 10.0.0.10 prefer
- ntp server 10.0.0.11
- logging host 10.0.0.20
- logging buffered 16384
- logging console critical
- service timestamps log datetime msec
save_when: modified # only write to NVRAM if changes were made
- name: Apply interface description (loop example)
cisco.ios.ios_config:
parents: "interface {{ item.name }}"
lines:
- "description {{ item.description }}"
loop:
- { name: GigabitEthernet0/1, description: "Uplink to Core-SW-01" }
- { name: GigabitEthernet0/2, description: "Uplink to Core-SW-02" }
Frequently Asked Questions
cisco.ios collection: ios_facts, ios_command, ios_config, ios_vlans, ios_interfaces, ios_bgp_global, ios_acls, and ios_banner. These cover the vast majority of day-to-day Cisco IOS automation tasks. For IOS-XE, the same collection works. For NX-OS, use cisco.nxos.cisco.ios, cisco.nxos, and cisco.iosxr for Cisco platforms, and junipernetworks.junos for Junos. You can manage mixed-vendor environments from the same control node. Use when: ansible_network_os == 'cisco.ios.ios' conditions to route tasks by platform within a single play.network_cli connection plugin, or via NETCONF for devices that support it. No software needs to be installed on your Cisco switches or routers — it uses the device's existing management SSH service.Free Cisco Config Templates
Download production-ready Cisco IOS configuration templates — hardened baselines, NTP/syslog standards, access layer configs — free from our template catalog.
Browse Free Templates →