Project: automated network config backups to Git
In short: This project pulls running configurations from your lab devices over SSH and commits them to a Git repository every night. Git keeps every version, so you can see exactly what changed, when, and roll back if needed. It is a small, safe, read-only project that shows real automation value.
Goal and what you will build
Configuration backups are the first thing most teams automate, because they are read-only, useful from day one and easy to explain to a manager. In this project you will build a Python script that connects to each device in an inventory, collects the running configuration, saves it as a text file and commits the result to a Git repository. Run nightly, it gives you a full history of every change on every device.
You need: Python 3, Git, and two or three lab devices (physical, or virtual images in a simulator such as GNS3, EVE-NG or Cisco Modeling Labs). Use only equipment you own or are authorised to manage, and a read-only or backup-only account on each device.
Design
- Inventory in YAML: hostname, management IP and Netmiko device type for each device. No passwords in this file.
- Credentials from environment variables (or a secrets manager), never in the script or repository.
- Clean-up: some lines change on every run, such as timestamps or
ntp clock-period. Removing them stops false "changes". - Git: one file per device, one commit per run, with a clear message. Push to a private remote if you have one.
- Error handling: one unreachable device must not stop the rest; failures are listed at the end.
# devices.yaml
- name: core-sw1
host: 192.168.10.2
device_type: cisco_ios
- name: edge-rtr1
host: 192.168.10.1
device_type: cisco_ios
- name: lab-fw1
host: 192.168.10.254
device_type: fortinet
Build it step by step
- Create a project folder with a virtual environment and run
pip install netmiko pyyaml. - Create a
configsfolder and rungit initinside it. Configurations contain sensitive data such as password hashes and SNMP communities, so keep this repository private and access-controlled. - Export credentials in your shell or service account:
NET_USERandNET_PASS. - Write the script below and run it by hand. Check the files and the Git log.
- Change a description on one lab device, run again and use
git diff HEAD~1to see the change. - Schedule it with cron or a systemd timer.
#!/usr/bin/env python3
"""Back up device configs to a Git repository."""
import os, re, subprocess, datetime
from pathlib import Path
import yaml
from netmiko import ConnectHandler
REPO = Path("configs")
COMMANDS = {"cisco_ios": "show running-config", "fortinet": "show full-configuration"}
NOISE = re.compile(r"^(! Last configuration change|! NVRAM config last updated|ntp clock-period)")
def clean(text):
return "\n".join(l for l in text.splitlines() if not NOISE.match(l)) + "\n"
def backup(dev):
params = {"device_type": dev["device_type"], "host": dev["host"],
"username": os.environ["NET_USER"], "password": os.environ["NET_PASS"]}
with ConnectHandler(**params) as conn:
out = conn.send_command(COMMANDS[dev["device_type"]], read_timeout=60)
(REPO / f"{dev['name']}.cfg").write_text(clean(out), encoding="utf-8")
def main():
devices = yaml.safe_load(open("devices.yaml", encoding="utf-8"))
failed = []
for dev in devices:
try:
backup(dev)
print("OK ", dev["name"])
except Exception as e: # keep going on errors
failed.append(dev["name"])
print("FAIL", dev["name"], type(e).__name__)
subprocess.run(["git", "-C", str(REPO), "add", "-A"], check=True)
stamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
subprocess.run(["git", "-C", str(REPO), "commit", "-q", "-m",
f"Backup {stamp} ({len(failed)} failed)"], check=False)
if failed:
print("Failed:", ", ".join(failed))
if __name__ == "__main__":
main()
# crontab -e : run at 01:30 every night
30 1 * * * cd /opt/netbackup && . .venv/bin/activate && ./backup.py >> backup.log 2>&1
Tip: git commit exits with an error when nothing changed, which is why the script uses check=False there. No commit simply means no device was changed.
How to extend it
- Run devices in parallel with Nornir or a thread pool to back up hundreds of devices quickly.
- Send an email or chat message when a configuration changes, including the
git diff. - Load the inventory from your source of truth instead of a YAML file.
- Mask secrets such as SNMP communities before committing, if the repository is shared more widely.
- Add a compliance check that runs on each new commit, linking this project to drift detection.
Showing it in your portfolio
Publish the code (never the real configurations or inventory) on GitHub with a README that explains the problem, the design diagram, how to install it and an example of the output. Include sample, sanitised configuration files and a screenshot or text excerpt of a git log and git diff showing a change being caught. In an interview, explain why you chose Git, how you protect credentials, and how the script copes with a device that is down. That story shows you think about operations, not just code.
Practice
Why remove lines such as "! Last configuration change" before committing?
Where should the device password come from in this project?
How would you see what changed on core-sw1 between yesterday and today?
Key takeaways
- Config backup is a safe, read-only first automation project.
- Git keeps every version and shows exactly what changed and when.
- Strip lines that change on every run to avoid false changes.
- Keep credentials out of code; keep the config repository private.
- Handle failures per device and schedule the job with cron or a timer.
Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.