Simple Automated Network Device Configuration Backups

Published by

on

Time to read:

4–6 minutes

In this post, we are going to go over a simple and easy way to implement automatic network device configuration backups. For this I will be using Ansible to connect onto each device and then copy their device configurations locally.

You can either leave the device configurations all on your Ansible Virtual Machine (VM) and then just backup that VM or better practise is to use a version control tool such as Git to backup the configurations.

NOTE: if you just want to configuration files then head over to here for the Github repository.


  1. Section I – Git Configuration
  2. Section II – Ansible Hosts File
    1. Example 1 – Ansible Hosts File – Local Accounts
    2. Example 2 – Ansible Hosts File – Single Account
  3. Section III – Ansible Vault
    1. Example 3 – Ansible Vault File – Local Account
    2. Example 4 – Ansible Vault File – Single Account
  4. Section IV – Ansible Playbook
    1. Example 5 – Ansible Playbook
  5. Section V – Automate Playbook
    1. Example 6 – Bash Script
    2. Example 7 – Crontab

Section I – Git Configuration

Pick where you want to push your configurations files to. For example, you could set up Github or Gitlab repository as a store for all your device configurations.

Once you have your repository made you just need to configure Git on the local Ansible VM. This can be achieved with the following commands when you are within the directory you want to backup the configurations from, in my example I will be using /Backups/:

git init
git remote add origin <repo url>
git config --global user.name "<name>"
git config --global user.email "<email>"
git branch -m <branch to work on>
git pull

Section II – Ansible Hosts File

We need to make a list of the devices that we want to backup using the following example as a template. This file is typically stored in ‘/etc/ansible/hosts‘.

If you are using a local account with a different password on each device then do the following:

[Cisco_IOS_Devices]
<IOS Device Name> ansible_host=<IP>

[Cisco_IOS_Devices:vars]
ansible_network_os=cisco.ios.ios
ansible_ssh_port=<port>
ansible_user=store[inventory_hostname]['user']
ansible_password=store[inventory_hostname]['pass']

[Cisco_ASA_Devices]
<Cisco ASA Name> ansible_host=<IP>

[Cisco_ASA_Devices:vars]
ansible_network_os=asa
ansible_network_terminal_errors=ignore
ansible_user=store[inventory_hostname]['user']
ansible_password=store[inventory_hostname]['pass']
ansible_become_password=store[inventory_hostname]['enable']
Example 1 – Ansible Hosts File – Local Accounts

If you are using a domain account with the same password on each device then do the following:

[Cisco_IOS_Devices]
<IOS Device Name> ansible_host=<IP>

[Cisco_IOS_Devices:vars]
ansible_network_os=cisco.ios.ios
ansible_ssh_port=<port>
ansible_user={{ CISCO_USER }}
ansible_password={{ CISCO_PASS }}

[Cisco_ASA_Devices]
<Cisco ASA Name> ansible_host=<IP>

[Cisco_ASA_Devices:vars]
ansible_network_os=asa
ansible_network_terminal_errors=ignore
ansible_user={{ CISCO_USER }}
ansible_password={{ CISCO_PASS }}
ansible_become_password=store[inventory_hostname]['enable']
Example 2 – Ansible Hosts File – Single Account

Section III – Ansible Vault

Lets get a secure place to store our passwords that will be used to login to devices. To do this we will utilise Ansible Vault.

To create the vault use the following command:

ansible-vault create /path/to/vault-file.yml

If you are using a local account to log into all the devices us the following:

SSH_KEY_PASS: <SSH Key Password>

store:
  <Cisco ASA Name>:
    user: <username>
    pass: <password>
    enable: <Enable Password>
  <IOS Device Name>:
    user: <username>
    pass: <password>
Example 3 – Ansible Vault File – Local Account

If you are using a single domain account to login to all the devices use the following:

CISCO_USER: <username>
CISCO_PASS: <password>
SSH_KEY_PASS: <SSH Key Password>

store:
  <Cisco ASA Name>:
    enable: <Enable Password>

Example 4 – Ansible Vault File – Single Account

If you are using Ansible vault and you want to run an Ansible playbook without interactively starting it you need some way of passing in the password. One way to do this is with a hidden file.

Create a new file '.password‘ and then in it have just the vault password.

Set the permissions so that only the user that start Ansible playbooks can read and write to it using the following commands:

chown user:group /path/to/.password
chmod 600 /path/to/.password

Section IV – Ansible Playbook

Now we can create the Ansible playbook that will go onto each device and get the configuration and then save that to a file. Once it is saved we can push it to our remote Git repository: NOTE: At the bottom of the playbook I am having to provide a password for my private key in order to push my backup configurations to Gitlab/Github.

- name: Create tmp Directory
  hosts: localhost
  gather_facts: false
  
  tasks:
    - name: Create tmp Directory
      ansible.builtin.file:
        path: /Backups/network-configuration-backup/tmp/
        state: directory
      delegate_to: localhost
      run_once: yes
      ignore_errors: yes

- name: Backup IOS Configurations
  hosts: Cisco_IOS_Devices
  gather_facts: false
  become: true
  connection: network_cli

  tasks:
    - name: Get IOS Device Configuration
      ios_command:
        commands: show run
      register: output_router

    - name: Save IOS Device Configuration
      copy:
        content: "{{ output_router.stdout[0] }}"
        dest: "/Backups/network-configuration-backup/tmp/{{ inventory_hostname }}.txt"

- name: Backup ASA Configurations
  hosts: Cisco_ASA_Devices
  gather_facts: false
  become: true
  connection: network_cli

  tasks:
    - name: Get ASA Device Configuration
      ios_command:
        commands: show run
      register: output_router

    - name: Save IOS Device Configuration
      copy:
        content: "{{ output_router.stdout[0] }}"
        dest: "/Backups/network-configuration-backup/tmp/{{ inventory_hostname }}.txt"


- name: Backup to Gitlab
  hosts: localhost
  gather_facts: false

  tasks:
    - name: Print Date
      command: "date +%Y%m%d"
      register: date
      changed_when: false
      run_once: yes
      delegate_to: localhost

    - name: Create Date Directory
      ansible.builtin.file:
        path: /Backups/network-configuration-backup/{{ date.stdout }}/
        state: directory
      delegate_to: localhost
      run_once: yes
      ignore_errors: yes

    - name: Move Items
      shell: |
        mv /Backups/network-configuration-backup/tmp/* /Backups/network-configuration-backup/{{ date.stdout }}/
        rm -fR /Backups/network-configuration-backup/tmp/
      delegate_to: localhost
      run_once: yes
      ignore_errors: yes

    - name: Git Commands
      shell: |
        git add .
        git commit -m "Backup Date {{ date.stdout }}"
      args:
        chdir: /Backups/network-configuration-backup
      delegate_to: localhost
      run_once: yes
      ignore_errors: yes
        
    - name: Git Push
      expect:
        command: git push
        responses:
          (?i)Enter passphrase for key '/home/<USER>/.ssh/id_rsa': "{{ SSH_KEY_PASS }}"
        chdir: /Backups/network-configuration-backup
      delegate_to: localhost
      run_once: yes
un_once: yes
Example 5 – Ansible Playbook

Section V – Automate Playbook

We have all the piece of the puzzle, so now lets bring it all together into a script that can run automatically.

Create a bash script, for example, mine is called ‘/Backup/backup.sh‘. Make sure it has the following in order to run the playbook:

ansible-playbook /path/to/playbook.yml --vault-password-file /path/to/.password -e @/path/to/vault.yml
Example 6 – Bash Script

Using the following command we need to make the bash script executable:

chmod +x /Backup/backup.sh

Now using the following command edit the crontab file:

crontab -e

Enter the following to run our automated backup playbook at the desired schedule:

*  1  *  *  2 /Backups/backup.sh
Example 7 – Crontab

Leave a comment