Multi-vendor network device backup tool built for ISPs and managed service providers. Backs up Mikrotik (RouterOS) and Cisco (IOS/NX-OS/XR/ASA) devices with automatic credential management, config change detection, email reporting, and a built-in security scanner.
Built by network engineers who run ISP infrastructure daily.
# Install dependencies
pip install librouteros netmiko
# Run the setup wizard
python3 isp_backup.py --setup
# Run your first backup
python3 isp_backup.pyThe setup wizard walks you through entering your device IPs (individual, ranges, or CIDR blocks), credentials, and optional email reporting. It writes fleet.json, credentials.json, and smtp.json to the script directory. That's it.
- Backs up Mikrotik routers via RouterOS API with FTP export retrieval. Handles ROS v6 and v7, including
show-sensitivefor v7 secrets and PPPoE secret extraction on v6. - Backs up Cisco/SSH devices via Netmiko. Auto-detects IOS, NX-OS, IOS-XR, and ASA. Supports password-only VTY auth on legacy gear.
- Auto-detects device type when given an unknown IP. Probes Mikrotik API first, falls back to SSH.
- Credential fallback tries multiple username/password pairs in order. Caches the last working credential per device so subsequent runs connect on the first attempt.
- Push user creates a known-good admin account on any Mikrotik router where a fallback credential was needed.
- Config change detection diffs every backup against the previous run (stripping volatile lines like timestamps and NTP clock-period). Changes are highlighted in the email report.
- Email reporting sends a summary after each run with success/failure counts, change diffs, and optionally a zip of all configs attached.
- Security scanner checks every Mikrotik device for known compromise indicators from CVE-2023-30799, TrickBot, Meris, and SOCKS proxy botnets.
- Threaded execution backs up 80+ devices in under 3 minutes with 12 parallel workers.
Requirements: Python 3.8+
pip install librouteros netmikoOn Debian/Ubuntu systems where pip complains about externally managed environments:
pip install librouteros netmiko --break-system-packagesNetmiko is optional. If not installed, Cisco/SSH backups are disabled and Mikrotik-only mode works fine.
python3 isp_backup.py --setupPrompts for your device fleet, credentials, and email config. Accepts IP input as:
| Format | Example | Result |
|---|---|---|
| Individual | 10.0.0.1, 10.0.0.2 |
2 hosts |
| Range | 10.0.0.1-24 |
24 hosts |
| CIDR | 192.168.88.0/24 |
254 hosts |
| CIDR (large) | 10.0.0.0/23 |
510 hosts |
| Mixed | 10.0.0.0/24, 172.16.1.1-5 |
259 hosts |
Copy the example configs and edit them:
cp examples/credentials.example.json credentials.json
cp examples/fleet.example.json fleet.json
cp examples/smtp.example.json smtp.json # optional
# Edit each file with your actual values# Back up everything
python3 isp_backup.py
# Mikrotik fleet only
python3 isp_backup.py --mikrotik-only
# Cisco fleet only
python3 isp_backup.py --cisco-only
# Single device (auto-detect type, save to fleet)
python3 isp_backup.py 10.0.0.50
# Single device, force Mikrotik on a private IP
python3 isp_backup.py 10.0.0.50 --mikrotik
# Probe without saving
python3 isp_backup.py 10.0.0.50 --nosave
# Retry failed devices
python3 isp_backup.py --retry 10.0.0.1,10.0.0.2 --mikrotik
# Show device status table
python3 isp_backup.py --list
# Security scan (full fleet)
python3 isp_backup.py --scanner
# Security scan (specific devices)
python3 isp_backup.py --scanner 192.168.88.1,10.0.0.1
# Progress bar instead of per-device scroll
python3 isp_backup.py --progress✓ 10.0.0.1 mikrotik edge-router-01 7.16.2
✓ 10.0.0.2 mikrotik tower-site-14 6.49.17
✓ 10.0.0.10 cisco core-sw01 15.2(2)E7
✗ 10.0.0.3 FAILED
==================================================
Completed : 3 backed up, 1 failed
Excluded : 1 router(s) skipped this run
Output dir: backups/mikrotik | /cisco
==================================================
Checks Mikrotik devices for indicators of compromise from known attack campaigns:
python3 isp_backup.py --scanner| Check | What It Detects |
|---|---|
| CVE-2023-30799 | RouterOS version vulnerable to privilege escalation |
| SOCKS proxy | Enabled SOCKS (TrickBot, Meris, 2025 SOCKS botnet) |
| Web proxy | HTTP proxy with injected error.html (cryptomining) |
| Schedulers | Tasks calling fetch() or referencing external URLs |
| Scripts | System scripts with external download references |
| Users | Accounts not in your credentials.json (e.g. 'service') |
| Files | Suspicious files on flash (.php, .html, .elf) |
| L2TP clients | Unknown L2TP clients (Meris 'lvpn' indicator) |
| DNS static | Static DNS entries (cache poisoning) |
| Firewall | Rules allowing port 5678, missing filter rules entirely |
| NAT redirects | dstnat redirect rules (traffic hijacking) |
| Services | Management interfaces with no IP restriction |
| Packet sniffer | Actively running packet capture (data exfiltration) |
your-scripts-dir/
├── isp_backup.py # The script
├── credentials.json # Login credentials (NEVER commit)
├── fleet.json # Device inventory (created by --setup)
├── smtp.json # Email config (optional)
├── device_credentials.json # Per-device credential cache (auto)
├── excluded_routers.json # Failed devices skipped next run (auto)
├── removed_routers.json # Permanently removed devices (auto)
├── last_email.txt # Most recent email body (auto)
└── backups/
├── mikrotik/ # .rsc exports
└── cisco/ # .cfg running-configs
Linux/WSL cron (daily at 2 AM):
0 2 * * * cd /path/to/scripts && python3 isp_backup.py >> backup.log 2>&1
Windows Task Scheduler:
Build a standalone exe first:
pip install pyinstaller
pyinstaller --onefile --name isp_backup isp_backup.pyThen point Task Scheduler at dist\isp_backup.exe with a start-in directory of wherever your config files live.
{
"mikrotik": [
{"username": "admin", "password": "secret1"},
{"username": "backup_user", "password": "secret2"}
],
"cisco": [
{"username": "admin", "password": "secret1", "secret": "enable_secret"}
],
"push_user": "admin",
"push_password": "secret1",
"push_group": "full",
"cisco_password_only": ["vty_password"]
}Credentials are tried in order. The first successful credential is cached per-device in device_credentials.json and tried first on future runs.
push_user is the account created on Mikrotik routers where a fallback credential was needed, ensuring you always have a known-good login.
cisco_password_only is for legacy IOS devices with password-only VTY authentication (no username prompt).
{
"mikrotik": [
"192.168.88.1",
"10.0.0.1",
"10.0.0.2"
],
"cisco": [
{"host": "10.0.0.10", "port": 22, "name": "core-sw01", "device_type": "cisco_ios"}
]
}Mikrotik entries can be plain IP strings or {"host": "...", "port": 8728} objects. Cisco entries require at minimum a host field. device_type values: cisco_ios, cisco_xe, cisco_xr, cisco_nxos, cisco_asa (leave blank for auto-detect).
{
"enabled": true,
"host": "smtp.example.com",
"port": 587,
"user": "alerts@example.com",
"password": "smtp_password",
"from": "alerts@example.com",
"to": ["ops@example.com"],
"subject": "Router Backup Report",
"timeout": 15
}Port 587 with a password triggers STARTTLS automatically. Port 25 with no password sends unauthenticated.
Run python3 isp_backup.py --help for the complete flag reference.
| Flag | Description |
|---|---|
--setup |
Interactive first-run configuration wizard |
--list |
Print device status table (no backup) |
--scanner [IPs] |
Run security scanner instead of backup |
--mikrotik-only |
Full run, Mikrotik devices only |
--cisco-only |
Full run, Cisco devices only |
--mikrotik |
Force Mikrotik API on a single target |
--cisco |
Force Cisco SSH on a single target |
--nosave |
Probe a device without adding to fleet |
--retry IPs |
Re-run specific devices, bypass exclusion list |
--progress |
Show progress bar instead of per-device scroll |
--password PWD |
Inject and save a credential for this run |
--username USER |
Pair with --password for a full credential |
--remove-exclusion IPs |
Clear devices from the exclusion list |
--remove-router IPs |
Permanently remove devices from fleet |
--attach-configs |
Zip and attach configs to email report |
--email-to ADDR |
Override email recipient for this run |
--debug-email |
Write SMTP debug transcript to smtp_debug.log |
--tmux |
Launch in a split-pane tmux session |
--reset-state |
Delete backups and state files |
--reset-devices |
Reset state + delete fleet.json |
--reset-all |
Reset everything + blank credentials template |
--v to --vvvvv |
Verbosity (CRITICAL to DEBUG) |
--debug/--info/etc |
Named verbosity levels |
Pull requests welcome. If you run an ISP or MSP and have device types or edge cases we don't handle, open an issue.
MIT. See LICENSE.