Skip to Content

How to Set Up Ansible for Cisco IOS Automation?

Ansible is a powerful automation tool used by many organizations worldwide. Initially, it gained popularity for managing Linux and Windows machines, but network automation was a trend that took some time to catch up. However, in recent times, even networking teams have started adopting the infrastructure-as-code strategy.

There are numerous automation tools available for network automation, but Ansible stands out as a popular choice due to its open-source nature and the backing of Red Hat.

One key advantage of Ansible is its idempotent nature. When defining changes, Ansible ensures that only the necessary modifications are made. If the desired state is already achieved, Ansible won’t make any further changes, allowing for reliable and consistent configurations.

How does Ansible make changes to Cisco IOS devices?

In Ansible, we use tasks in a playbook to configure network devices, using those tasks, it establish an SSH connection to the device to read the configuration or implement changes, when we run the playbook. 

These tasks utilise modules, such as the “ios_command” module which enables executing commands like “show version” on Cisco IOS devices.

When it comes to making changes on Cisco IOS devices, the “ios_configure” module becomes useful. This module, along with others like “ios_ntp” “ios_banner” “ios_vlans” and “ios_l2_interfaces” etc. provides specific functionality for different use cases.

For Cisco IOS environments, Ansible offers a comprehensive set of modules to automate Cisco infrastructure, covering various aspects of network management.

You can checkout all the modules from official documentation here.

It’s worth noting that Ansible provides modules for other network vendors as well, such as Fortinet, Palo Alto, and more. So, if you’re considering Ansible for networking automation, exploring these additional modules can be beneficial.

In this blog article, we will focus on setting up Ansible control nodes for network automation, primarily targeting Cisco IOS software. This setup will empower you to manage production networks effectively. You can even extend the configuration management to version control platforms like Bitbucket.

By the end of this article, you will have a solid understanding of setting up Ansible for Cisco IOS automation and its application for a production network management.

Can I install ansible in windows ?

Ansible is based on a python programme and it can install in both mac and linux operating system, however when it comes to windows, you will have to install Linux subsystem for windows in order for you to install ansible.

If you are a windows user, I would recommend you install any linux operating system as a virtual machine and then try using ansible in it.

You can follow the article below to learn more about the installation of Linux on windows.

With that, let’s go ahead and proceed with the installation of Ansible on a ubuntu machine for Cisco IOS automation.

Step1. Install the ansible software package.

I am using an Ubuntu desktop version 22.04 in this lab, if you have different versions of linux then the commands will be a little different.

Check out the ansible documentation here to follow the installation instructions on other versions of linux.

Enter the below commands to install ansible on your Ubuntu host.

sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y

Once the installation is successful you can check the version of ansible by typing the command ansible --version

As you can see, I am on version 2.14.6 at the time of this writing.

How to fix ansible local encoding error ?

Sometimes, you may encounter the following error message when attempting to check the Ansible version: Ansible requires the locale encoding to be UTF-8; Detected ISO8859-1.

saif@saif-pc:~$ ansible --version
ERROR: Ansible requires the locale encoding to be UTF-8; Detected ISO8859-1.
saif@saif-pc:~$

To resolve this issue, follow these simple steps:

  • First, check the locale settings by running the command.locale In the output, you’ll observe that the locale is set to en_IN without encoding in my case.
  • If you wish to maintain the en_IN locale with UTF-8 encoding, use the following command:
export LANG=en_IN.UTF-8

Alternatively, if your preferred language is en_US, utilise the following command:

export LANG=en_US.UTF-8
  • After executing the appropriate command, check the encoding again. Now, you’ll notice that it has been updated to UTF-8.

Verify the Ansible version once more. You’ll observe that the error message no longer appears.

Step2. Install the cisco ios modules for ansible.

When it comes to ansible there are different modules supported by each vendor, for example in the case of Cisco, you cannot start to use all the cisco modules right out of the box after the installation of ansible. 

You first need to install the Cisco IOS modules using ansible collections. Which by default uses ansible galaxy repository here.

Where you can click on search on the left pane and search for cisco ios, and click on the ios collection.

Here you can select the version of the collection. And you can also see the command to install the collections.

In case, if you require different versions, you may choose the version of your choice from the install version drop down and the installation command will change accordingly.

Copy the ansible installation command and paste it on the ubuntu terminal and then hit enter.

In few seconds the ansible cisco ios collection will be installed on your machine.

Step3. Ansible Directory Structure for Network Automation.

After the ansible installation the important part is to setup the directory structure for the ansible to use, each directories represents different things. Lets set them up.

We are going to follow ansible recommendations to set up directories in our control node. We are not completely sticking with the standard, I modified it according to the Cisco ios network automation setup.

You can learn more about the ansible best practices here.

Below are the directories that we are going to create first.

Host_vars: In this section, we will organise our Cisco running configurations as YAML files within the host_vars directory. 

These files act as variables that can be referenced in Ansible tasks when needed. 

Within host_vars, you can create subfolders for different environments such as production and staging.

For instance, if you have a Cisco switch named site1-sw-01 with its running configuration, you can create a production folder within host_vars and then add a site1 folder inside it. 

Inside this site1 folder, you can store the host_vars as YAML or JSON files as shown below.

/host_vars/production/site1/site1-sw-01.yml

Production: This directory is dedicated to storing host_var files for production sites, with each site having its own file.

Staging: If you have a lab or staging environment, you can store the lab-specific host_var files here.

Inventories: The inventory file is where we define and store host information such as inventory hostnames, SSH keys, credentials, and other parameters. The structure of the host_var folders (production and staging) is mirrored within the inventories directory.

Group_vars: While Ansible allows creating group vars to hold configuration common to a group, we will not be using that approach. Instead, we will utilise the default folder within the roles directory, which we will look later.

Playbooks: All the playbooks will be stored in this directory.

Roles: This directory is dedicated to setting up roles specifically for each vendor, such as Cisco, Fortinet, Palo Alto, and so on. Create a roles folder to organize and manage these roles effectively.

The overall folder structure should resemble the following:


├── host_vars
│   ├── production
│   │   ├── site1
│   │   │   └── host_vars.yml
│   │   ├── site2
│   │   │   └── host_vars.yml
│   │   └── ...
│   └── staging
│       ├── lab1
│       │   └── host_vars.yml
│       ├── lab2
│       │   └── host_vars.yml
│       └── ...
├── inventories
│   ├── production
│   │   ├── site1
│   │   │   └── inventory.yml
│   │   ├── site2
│   │   │   └── inventory.yml
│   │   └── ...
│   └── staging
│       ├── lab1
│       │   └── inventory.yml
│       ├── lab2
│       │   └── inventory.yml
│       └── ...
├── group_vars
│   └── default
│       └── group_vars.yml
├── playbooks
│   ├── playbook1.yml
│   ├── playbook2.yml
│   └── ...
└── roles
    ├── cisco
    ├── fortinet
    ├── palo_alto
    └── ...

I have three sites, Bangalore(BLR), California(CAL) and London(LON) and here in my lab, this is how I have set it up. Hope it does make sense now.


├── host_vars
│   ├── production
│   │   ├── blr
│   │   ├── cal
│   │   └── lon
│   └── staging
│       └── cal_lab
├── inventories
│   ├── production
│   │   ├── blr
│   │   ├── cal
│   │   └── lon
│   └── staging
│       └── cal_lab
├── playbooks
└── roles

As you can see at the bottom, we just created a roles folder, which we are going to expand now.

Step4. Setup Cisco roles in Ansible.

Now that we have set up the directory structure for Cisco networking, let’s now go ahead and add a role specifically for Cisco IOS.

Roles allow you to encapsulate reusable configurations and easily apply them to multiple hosts or environments.

In Cisco or any other network vendors for that matter, there are common configurations such as DNS, NTP, Radius, SNMP etc. And unique configuration such as hostname, interface IP configuration, VLAN information and so on.

So we are going to create two roles.

  1. Cisco_standard – where we keep the common configuration.
  2. Cisco_unique – where we keep the unique configuration.

You can further call this role into your playbook using different conditions.

Let’s set up the roles in ansible.

Goto roles directory and issue the below commands for each.

ansible-galaxy init cisco_standard
ansible-galaxy init cisco_unique

Once role added, you can see the message Role was created successfully.

Now you can see, two folders created in roles directory.

if you expand cisco_standard or cisco_unique folder, you can see multiple subdirectories, each representing different items.

We dont require all the subfolders for the cisco ios playbook, We will go through some of them though.


In the “cisco_standard” configuration folder, our primary focus lies in the “defaults” folder. Here, we keep the standard configuration in the “main.yml” file, similar to the structure of the “group_vars” folder.

This means that all the common configuration settings can be conveniently stored here, and they will be applied uniformly to all devices within a specific site.

Furthermore, the corresponding tasks for the standard configuration are also stored in the “tasks” folder.

Now, when it comes to the Cisco unique configuration directory, we solely rely on the “tasks” folder. Here, we specify the tasks that need to be executed, while the variables are extracted from the “host_var” files.

I understand that the connections between these puzzle pieces may still be unclear to you as you’re just getting started with Ansible control node setup for Cisco IOS network automation. However, once you begin running multiple playbooks, everything will start falling into place.

To ensure you’re not left empty-handed, our next step will be to delve into our very first Cisco playbook here. This playbook will enable us to make changes directly on the Cisco switch.