Time to read:
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.
- Section I – Git Configuration
- Section II – Ansible Hosts File
- Section III – Ansible Vault
- Section IV – Ansible Playbook
- Section V – Automate Playbook
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


Leave a comment