Ansible Interface Playbook (ios_config): Cisco interface config

Here an Ansible Playbook with three different examples how to configure Cisco router interfaces:

1. Static IP address configuration in playbook
2. Configuration comes out of Jinja2 template, can be run dynamic with variables
3. Loop in playbook configures multiple interfaces

There are some disadvantages to work with templates, if you use commands like “no shutdown” to enable the interface. They are not shown in the running-configuration which means Ansible will assume that the configuration is not matching and execute the template again.
Another disadvantage with templates is that you cannot run “before” or “after” commands to remove existing configuration all this needs to be implemented in your Jinja2 template.

Here the Ansible Playbook:

- name: Cisco interface config
  connection: local
  hosts: all
  gather_facts: false
      username: "{{ username }}"
      password: "{{ password }}"
      host: "{{ device_ip }}"
    - name: configure IP address
          - default interface FastEthernet1/0
          - ip address
          - no shutdown
        match: strict
        parents: interface FastEthernet1/0
        provider: "{{ cli }}"

    - name: configure IP out of template
        src: "interfaces.j2"
        provider: "{{ cli }}"

    - name: configure IP with loop
        provider: "{{ cli }}"
          - "default interface {{ item.interface }}"
          - "ip address {{ item.address }}"
          - no shutdown
        parents: "interface {{ item.interface }}"
        - { interface : FastEthernet2/0, address : }
        - { interface : FastEthernet2/1, address : }

Read my new posts about Ansible Playbook for Cisco ASAv Firewall Topology or Ansible Playbook for Cisco BGP Routing Topology.

Ansible Semaphore

I spend lot of time working with Ansible in the last weeks to automate the deployment of Cisco router or Cumulus switches. (Waiting for Ansible 2.2 to support Cisco ASA devices..)
Ansible is a great tool but if you have multiple YAML files and various roles it can get pretty messy and would be nice to have central tool to trigger your tasks and structure your environment variables or inventories.

I exactly found this tool with Ansible Semaphore:

The install is pretty easy and provides an API to trigger your tasks remotely.

You can create different projects and include your Ansible YAML files.


The source is a Git repository where your files are stored:


Here your environment variables:


Inventory definition:


Finally the you can execute your Ansible YAML files via the Web UI or API:



Have fun playing around with Semaphore 🙂

Cisco IOS automation with Ansible

Bin a long time since I wrote my last post, I am pretty busy with work redesigning the data centres for my employer. Implementing as well an SDN Software-defined Network from VMware NSX but more about this later.

Ansible released some weeks ago new core modules which allows you to push directly configuration to Cisco IOS devices. More information you find here:

I created a small automation lab in GNS3 to test the deployment of configs via Ansible to the two Cisco routers you see below. I am running VMware Fusion and used the vmnet2 ( network for management because I run there my CentOS VM from where I deploy the configuration.

Don’t forget you need to pre-configure your Cisco router that you can connect via SSH to deploy the configuration.

Here the folder and file script structure of my Ansible example, under roles you have the different tasks I would like to execute common and logging but as well dependencies writecfg which saves the running-config to startup-config:


The site.yml is the main script which I execute with Ansible which includes different roles for common and logging configuration:

- name: Cisco baseline configuration
  connection: local
  hosts: ios 
  gather_facts: false

    - role: common
      tags: common
    - role: logging
      tags: logging

In the hosts file, I define the hostname and IP addresses of my IOS devices

rtr01 device_ip=
rtr02 device_ip=

The file group_vars/all.yml defines variables which I used when the script is executed:

username: "ansible"
password: "cisco"
secret: "cisco"

Under the roles/../meta/main.yml I set a dependency on the writecfg handler to save the configuration later when I change anything on the device.

Under the roles/../tasks/main.yml I define the module which I want to execute and the template I would like to deploy

Under the roles/../templates/.. you find the Jinja2 template files which include the commands.

Under roles/writecfg/handler/main.yml is the dependencies I have with the two roles common and logging to save the configuration if something is changed on the router.

To execute the cisco-baseline Ansible script just execute the following command and see the result:

[[email protected] cisco-baseline]$ ansible-playbook site.yml -i hosts

PLAY [Ensure basic configuration of switches] **********************************

TASK [common : ensure common configuration exists] *****************************
ok: [rtr02]
ok: [rtr01]

TASK [logging : ensure logging configuration exists] ***************************
changed: [rtr02]
changed: [rtr01]

RUNNING HANDLER [writecfg : write config] **************************************
ok: [rtr01]
ok: [rtr02]

PLAY RECAP *********************************************************************
rtr01                      : ok=3    changed=1    unreachable=0    failed=0
rtr02                      : ok=3    changed=1    unreachable=0    failed=0

[[email protected] cisco-baseline]$

Read my new posts about Ansible Playbook for Cisco ASAv Firewall Topology or Ansible Playbook for Cisco BGP Routing Topology.