Network Configuration Backup with Ansible and Git

Network Configuration Backup with Ansible and Git
In: NetDevOps, Ansible

The typical way you would perform Network Configuration Backup is by using NCM software such as Solarwinds NCM, Rancid, Oxidized etc. However, you can also utilise Ansible and Git to perform the backups. I know it sounds silly, why would anyone do it? But believe me, it requires very little time and effort to deploy and manage.

In this blog post, I will show you how to perform scheduled configuration backups using Ansible and Git. Ansible will backup the config and Git will perform version control.

I highly recommend you to check out my previous Ansible introduction posts below:

Ansible with Cisco - Part 1 Installation and basic set up
Installation I’m going to install Ansible on my Raspberry Pi for this examle. You can use any other OS including Ubuntu, MacOS etc. Our end goal is to manage both of the routers via Ansible. In this example, we will get the ‘show version | incl Version’ output on both routers using a very basic Ansi…
Ansible and Cisco example - config_module
In this blog post, I will show you how to make basic configuration changes on the Cisco IOS router using Ansible ios_config module.

Setting up the environment


I have a very basic set-up with:

  • 1 x ASA
  • 1 x IOS Router
  • 1 x Ansible Control Machine

and GitLab hosted locally.


Ansible copies the running configuration from each device daily and saves it into a directory /home/ubuntu/cisco-backups in the same machine.

Please note that If there are no changes to the running-config then Ansible will not replace the existing file.

Ansible also runs Git commands into that directory so, the changes are committed and pushed to the GitLab repository every day.


Git is a distributed version control system for tracking changes in any set of files. I'm going to use GitLab to manage the repositories in this example. You can also use GitHub or BitBucket.

  • Create a new project on GitLab
  • Clone the repository to the local host
Create New Project
Project Description
Git Clone
ubuntu@ubuntu:~$ git clone git@gitlab.packet.lan:root/cisco-backups.git
Cloning into 'cisco-backups'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

You can install GitLab using this guide: Download and install GitLab | GitLab

File structure

ubuntu@ubuntu:~/config_backup$ tree      <<< Ansible playbook
├── inventory
│   ├── group_vars
│   │   ├── firewall.yml
│   │   └── ios.yml
│   └── hosts
├── playbooks
│   ├── ansible.cfg
│   ├── config_backup.yml
│   └── show_command.yml


ubuntu@ubuntu:~/cisco-backups$ tree      <<< Backups


ubuntu@ubuntu:~/config_backup/inventory$ cat hosts 
asa ansible_host=

router-1 ansible_host=

host file

ubuntu@ubuntu:~/config_backup/inventory/group_vars$ cat firewall.yml 

ansible_network_os: asa
ansible_user: ansible
ansible_password: Cisco123
ansible_become: yes
ansible_become_password: Cisco123

ubuntu@ubuntu:~/config_backup/inventory/group_vars$ cat ios.yml 

ansible_network_os: ios
ansible_user: ansible
ansible_password: Cisco123
ansible_become: yes
ansible_become_password: Cisco123


Please note that in a production environment you shouldn't save the credentials in plain text. Please check out my previous Ansible articles to find out how to use Ansible Vault to encrypt sensitive information.

ubuntu@ubuntu:~/config_backup/playbooks$ cat config_backup.yml 

  hosts: firewall
  gather_facts: false
  connection: network_cli

    - name: ASA CONFIG
        commands: show run
      register: output

    - name: SAVE ASA CONFIG
        content: "{{ output.stdout[0] }}"
        dest: "/home/ubuntu/cisco-backups/show_run_{{ inventory_hostname }}.txt"

  hosts: ios
  gather_facts: false
  connection: network_cli

    - name: IOS CONFIG
        commands: show run
      register: output_router

    - name: SAVE IOS CONFIG
        content: "{{ output_router.stdout[0] }}"
        dest: "/home/ubuntu/cisco-backups/show_run_{{ inventory_hostname }}.txt"

  hosts: localhost


    - name: print time
      command: date
      register: time
      changed_when: false
      delegate_to: localhost
      run_once: yes

    - name: git commands
      shell: |
        git add .
        git commit -m "Device Backup on {{time.stdout}} "
        git push
        chdir: /home/ubuntu/cisco-backups
      delegate_to: localhost
      run_once: yes


Few things to consider

  • command: date - Ansible prints out the current date and time and pass it as the Git commit message. So, we can easily find out when a config change was made.
  • delegate_to: localhost - We are telling Ansible to run the commands on the localhost
  • chdir: - Change the directory

Run the playbook

ubuntu@ubuntu:~/config_backup/playbooks$ ansible-playbook config_backup.yml 

PLAY [FIREWALLS] *********************************************************************************************************************************************************************************

TASK [ASA CONFIG] ********************************************************************************************************************************************************************************
ok: [asa]

TASK [SAVE ASA CONFIG] ***************************************************************************************************************************************************************************
changed: [asa]

PLAY [IOS ROUTERS] *******************************************************************************************************************************************************************************

TASK [IOS CONFIG] ********************************************************************************************************************************************************************************
ok: [router-1]

TASK [SAVE IOS CONFIG] ***************************************************************************************************************************************************************************
changed: [router-1]

PLAY [GIT SECTION] *******************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
ok: [localhost]

TASK [print time] ********************************************************************************************************************************************************************************
ok: [localhost -> localhost]

TASK [git commands] ******************************************************************************************************************************************************************************
changed: [localhost -> localhost]

PLAY RECAP ***************************************************************************************************************************************************************************************
asa                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
router-1                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Running the Playbook

Let's verify the config files

As you can see below Ansible copies the running config files into the Git Directory.

ubuntu@ubuntu:~$ ls -l cisco-backups/
total 20
-rw-rw-r-- 1 ubuntu ubuntu   17 Dec  7 15:34
-rw-rw-r-- 1 ubuntu ubuntu 7715 Dec  7 15:39 show_run_asa.txt
-rw-rw-r-- 1 ubuntu ubuntu 5138 Dec  7 15:39 show_run_router-1.txt

Check the GitLab repository

As you can see below the files are also pushed to GitLab.


Let's make a small config change on both ASA and IOS router and see what happens.

CISCO-ASA# conf ter
CISCO-ASA(config)# interf
CISCO-ASA(config)# interface gi0/2
CISCO-ASA(config-if)# nameif
CISCO-ASA(config-if)# nameif SERVERS
INFO: Security level for "SERVERS" set to 0 by default.
CISCO-ASA(config-if)# ip add
CISCO-ASA(config-if)# ip address
CISCO-ASA(config-if)# exit
CISCO-ASA(config)# obj
CISCO-ASA(config)# object net
CISCO-ASA(config)# object network VMWARE
CISCO-ASA(config-network-object)# host
CISCO-ASA(config-network-object)# end

router-1(config)#access-list 25 permit any 

Making Config Changes

Let's run the Playbook again

ubuntu@ubuntu:~/config_backup/playbooks$ ansible-playbook config_backup.yml 

Run Playbook

As you can see below Git is showing what has been changed since the last commit.

ASA Diff
IOS Diff

Removing unwanted lines

As you can see above, Git is registering cryptochecksum:as a change. You can actually remove that line from the configuration file by using Ansible lineinfile module. Please make sure to add this task above the GIT SECTION.

    - name: Remove Lines from ASA
        path: /home/ubuntu/cisco-backups/show_run_{{ inventory_hostname }}.txt
        regexp: 'Cryptochecksum:*' 
        state: absent

You can set up a cron job to automatically run the playbook daily at specific time. The below will run the playbook each day 1 AM.

0 1 * * * /usr/bin/ansible-playbook /home/ubuntu/config_backup/playbooks/config_backup.yml

cron job

GitHub - vsurresh/ncm-with-ansible-git: Network Configuration Management with Ansible and Git
Network Configuration Management with Ansible and Git - GitHub - vsurresh/ncm-with-ansible-git: Network Configuration Management with Ansible and Git

Thanks for reading.

As always, your feedback and comments are more than welcome.

Written by
Suresh Vina
Tech enthusiast sharing Networking, Cloud & Automation insights. Join me in a welcoming space to learn & grow with simplicity and practicality.
More from Packetswitch
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Packetswitch.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.