Network engineers spend a lot of time keeping device configurations safe. Manual copy‑and‑paste or copy‑to‑TFTP can be tedious and error‑prone, especially in larger environments. Python, with its rich ecosystem of networking libraries, offers a clean, repeatable way to back up routers, switches, and firewalls. In this guide we’ll walk through building a lightweight backup script powered by Netmiko, the most popular SSH library for network automation. By the end you’ll have a fully functional, schedule‑able backup solution that can be extended to any vendor Netmiko supports.
What You’ll Need
- A laptop or server with Python 3.8+ installed.
- Access to the network devices you want to back up (SSH enabled, credentials, and proper permissions).
- Administrative rights to install packages or create a virtual environment.
- Optional: a version control system (Git) to track backup history.
Step 1: Set Up Your Python Environment
Start by creating a clean virtual environment so that the project’s dependencies don’t clash with other Python tools. Open a terminal and run:
python3 -m venv netmiko‑env
source netmiko‑env/bin/activate
pip install --upgrade pip
pip install netmiko pyyaml
We’re installing netmiko for SSH communication and pyyaml to parse a YAML inventory file. The netmiko‑env folder will contain all the libraries you need.
Step 2: Create a Device Inventory
Netmiko can handle a single device or a list of devices. For scalability, we’ll keep the device list in a YAML file called inventory.yml. Here’s a minimal example:
---
devices:
- host: 10.1.1.1
device_type: cisco_ios
username: admin
password: "P@ssw0rd"
secret: "cisco"
- host: 10.1.1.2
device_type: juniper_junos
username: admin
password: "P@ssw0rd"
secret: ""
Notice we store the enable password in the secret field. Netmiko will automatically enter enable mode if a secret is provided.
Step 3: Skeleton Backup Script
Create a file named backup.py and add the following skeleton. This script will load the inventory, iterate over devices, and call a backup routine for each.
import os
import datetime
import yaml
from netmiko import ConnectHandler
# Load inventory
with open('inventory.yml') as f:
inventory = yaml.safe_load(f)
# Directory to store backups
BACKUP_DIR = 'backups'
os.makedirs(BACKUP_DIR, exist_ok=True)
# Timestamp format
TIMESTAMP = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
for dev in inventory['devices']:
try:
print(f"Connecting to {dev['host']}...")
net_connect = ConnectHandler(**dev)
if dev.get('secret'):
net_connect.enable()
config = net_connect.send_command('show running-config', use_textfsm=False)
filename = f"{dev['host']}_{TIMESTAMP}.cfg"
with open(os.path.join(BACKUP_DIR, filename), 'w') as f:
f.write(config)
net_connect.disconnect()
print(f"Backup saved to {filename}")
except Exception as e:
print(f"Error on {dev['host']}: {e}")
Run the script once to verify it works:
python backup.py
You should see a new file in the backups folder for each device.
Step 4: Add Error Handling & Logging
Production scripts need robust error handling. Replace the print statements with Python’s logging module and capture exceptions gracefully. Add the following at the top of backup.py:
import logging
logging.basicConfig(filename='backup.log',
level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s')
Then modify the loop:
for dev in inventory['devices']:
try:
logging.info(f"Connecting to {dev['host']}")
net_connect = ConnectHandler(**dev)
if dev.get('secret'):
net_connect.enable()
config = net_connect.send_command('show running-config', use_textfsm=False)
filename = f"{dev['host']}_{TIMESTAMP}.cfg"
with open(os.path.join(BACKUP_DIR, filename), 'w') as f:
f.write(config)
net_connect.disconnect()
logging.info(f"Backup saved to {filename}")
except Exception as e:
logging.error(f"Error on {dev['host']}: {e}")
This logs all actions to backup.log, making troubleshooting straightforward.
Step 5: Implement Backup Rotation
Old backups can consume disk space. We’ll keep the most recent 7 days. Add a helper function before the loop:
def rotate_backups(directory, days=7):
now = datetime.datetime.now()
for file in os.listdir(directory):
path = os.path.join(directory, file)
if os.path.isfile(path):
file_time = datetime.datetime.fromtimestamp(os.path.getmtime(path))
if (now - file_time).days > days:
os.remove(path)
logging.info(f"Removed old backup {file}")
Call rotate_backups(BACKUP_DIR) at the start of the script. This keeps the backup folder tidy without manual intervention.
Step 6: Schedule Backups with Cron
Automation is only useful if it runs unattended. On Linux or macOS, open the crontab editor:
crontab -e
Add a line to run the script daily at 02:00 AM:
0 2 * * * cd /path/to/your/project && ./netmiko-env/bin/python backup.py
On Windows, use Task Scheduler to create a new task that triggers at the same time and runs python backup.py with the environment activated. Ensure the task runs with a user account that has network access and file permissions.
Common Mistakes to Avoid
1. Wrong device_type – Netmiko relies on accurate device_type strings. A typo (e.g., cisco_ios vs cisco_iosxe) can cause connection failures. Verify the value against the Netmiko docs.
2. Not escaping passwords – If a password contains quotes or special characters, wrap it in double quotes in YAML or escape it. Example: password: "P@ss'w0rd!".
3. Ignoring SSH key verification – By default Netmiko uses ssh‑client key verification. In scripts, set global_delay_factor or use_keys=False if you encounter authentication prompts.
4. Not handling timeouts – Add timeout=60 to ConnectHandler to prevent hanging on unreachable devices.
5. Storing credentials in plain text – For production, consider environment variables or a secrets manager (e.g., HashiCorp Vault, AWS Secrets Manager).
Tips and Tricks
• Use a configuration file for global settings (e.g., backup directory, retention days) instead of hard‑coding them.
• Leverage Netmiko’s send_config_from_file if you need to push changes after backup.
• Integrate with Git – Commit backups to a private Git repo; this gives you a versioned history and easy diffing.
• Encrypt backups – Use openssl or Python’s cryptography library to encrypt the config files before storing.
• Parallelize with ThreadPoolExecutor – For dozens of devices, run connections concurrently to cut runtime.
Frequently Asked Questions
Can Netmiko back up devices from other vendors like Arista or Palo Alto?
Yes. Netmiko supports many vendors. Add the appropriate device_type (e.g., arista_eos, paloalto_panos) and use the same show running-config command or vendor‑specific command if needed.
How do I secure my backup files?
Store backups on a secure, access‑controlled server. Encrypt them with AES-256 and rotate encryption keys. Use file‑system permissions to restrict read access to only privileged users.
What if a device’s configuration is very large (hundreds of MB)?
Netmiko streams the output line by line. For very large configs, increase global_delay_factor or use send_command_timing with a longer timeout. Consider chunking the output if memory becomes an issue.
Can I restore a backup using this script?
Netmiko can send configuration commands, but restoring a full config usually requires the vendor’s copy or configure replace commands. You can extend the script to read a file and execute the appropriate restore command.
Why choose Netmiko over NAPALM?
Netmiko offers a lightweight, SSH‑only approach with minimal overhead. NAPALM provides a richer abstraction layer but requires a larger dependency set. For simple backup tasks, Netmiko is faster to set up.
Conclusion
Automating network device backups with Python and Netmiko is a practical way to reduce manual effort, eliminate human error, and create a reliable audit trail. By following the steps above—setting up a virtual environment, organizing an inventory, writing a robust script, adding logging and rotation, and scheduling with cron—you’ll have a production‑ready backup system in no time. Remember to keep credentials secure, monitor logs for failures, and periodically test restores to ensure your backups are truly reliable. Happy automating!
Photo by Taylor Vick on Unsplash





