DevOps Tools Network Automation 156 vues

Stop Losing Network Configs at 3 AM! Use VIBENetBackup Instead

B
Bright Coding
Auteur
Stop Losing Network Configs at 3 AM! Use VIBENetBackup Instead

Stop Losing Network Configs at 3 AM! Use VIBENetBackup Instead

It's 3:47 AM. Your phone explodes with alerts. The core switch at your remote datacenter just died—and the last configuration backup you have is from eight months ago. The junior engineer who made critical VLAN changes never documented them. Your RTO just went from minutes to days. Your CFO is about to learn what "resume-generating event" really means.

Sound familiar? Here's the brutal truth: most network teams are one failed device away from disaster. Manual show run copy-pastes, scattered TFTP servers, and "I'll back it up next week" promises don't scale. They break. They get forgotten. They cost you sleep, sanity, and sometimes your job.

But what if your network configs backed themselves up automatically? What if you could detect exactly what changed between yesterday's backup and today's? What if deploying this took literally five minutes?

Enter VIBENetBackup—the open-source network configuration backup manager that top infrastructure engineers are quietly deploying while everyone else is still wrestling with cron scripts and USB drives. Multi-engine support, automated scheduling, intelligent retention, and a gorgeous web UI that actually makes backup management enjoyable. This isn't just another backup tool. It's your insurance policy against 3 AM nightmares.


What is VIBENetBackup?

VIBENetBackup is a modern, open-source network device configuration backup manager built by Kulunki Labs. Born from the frustration of managing heterogeneous network environments with cobbled-together scripts, it delivers enterprise-grade backup automation without the enterprise-grade price tag—or complexity.

At its core, VIBENetBackup solves a deceptively simple problem: how do you reliably back up configurations from dozens (or hundreds) of network devices across multiple vendors, protocols, and locations? The answer, it turns out, requires sophisticated engineering. Version 1.6.8 (released April 2026, MIT licensed) represents the culmination of rapid iteration based on real-world production feedback.

The project is built on a rock-solid Python↗ Bright Coding Blog stack—FastAPI for the backend API, SQLAlchemy for database operations, Bootstrap 5 with HTMX for the responsive web interface, and APScheduler for cron-based job execution. This isn't a fragile shell script collection; it's a full-featured application with encrypted credential storage, session-based authentication, and a comprehensive REST API.

What's driving its rapid adoption? Three forces are converging. First, network infrastructure is exploding in complexity—SD-WAN, cloud on-ramps, IoT gateways—making manual backup approaches impossible. Second, compliance requirements (SOC 2, ISO 27001, PCI-DSS) increasingly mandate verifiable configuration backup and change tracking. Third, the tool's Docker↗ Bright Coding Blog-first deployment and one-liner install remove every friction point that kills adoption.

The secret sauce? Multi-engine architecture. While competitors lock you into a single collection method, VIBENetBackup speaks SSH via Netmiko, SCP for file transfers, REST APIs for pfSense/OPNsense and Oxidized integration, and even handles Proxmox VE's complex multi-file configurations. One tool. Every device. Zero compromises.


Key Features That Separate VIBENetBackup from the Pack

Let's dissect what makes this tool genuinely powerful—not just marketing bullet points, but technical capabilities that solve real problems.

Multi-Engine Backup Collection The engine system is modular and extensible. Netmiko handles SSH-based CLI collection for Cisco IOS/XE/XR/NX-OS, Nokia SR OS, Arista EOS, Juniper JunOS, HP/Aruba, Dell, MikroTik, and more. SCP enables direct file transfer for devices supporting it. The Oxidized REST API engine lets you migrate incrementally from existing Oxidized deployments. pfSense/OPNsense API and Proxmox VE engines handle specialized platforms that don't expose standard SSH config commands. Each engine is a pluggable Python module with standardized interfaces.

Multi-Destination Storage with Compression Backups aren't useful if they're trapped on one server. VIBENetBackup writes to local filesystem, Git repositories (GitHub, Gitea, Forgejo for GitOps workflows), and SMB/CIFS shares—with optional gzip compression to save space. The v1.6.7 release added multi-destination recording, so a single backup can simultaneously land in local storage AND your Git repo AND the SMB share, with each destination tracked individually.

Grandfather-Father-Son Retention with Automated Maintenance Forget manual cleanup scripts. The GFS rotation automatically maintains daily, weekly, and monthly backup tiers. A daily maintenance job at 3:30 AM sweeps stale backups, purges old job history (90-day default), runs SQLite VACUUM for performance, and cleans orphaned records. Your storage costs stay predictable.

Cryptographic Change Detection Every backup gets a SHA256 hash. The system automatically compares against previous backups, flagging "Changed" vs "Unchanged" states. The unified diff viewer lets you compare any two revisions side-by-side—critical for audit trails and troubleshooting "what changed when everything broke."

Apprise-Powered Notification Ecosystem With 100+ notification services supported via Apprise, you're not limited to basic email. Slack, Discord, Telegram, Microsoft Teams, PagerDuty, custom webhooks—configure multiple channels per severity level. Encrypted URL storage keeps your webhook secrets safe.

Security-First Design Credentials use Fernet symmetric encryption. Sessions are 14-day cookie-based with HMAC-SHA256 signed tokens—no JWT complexity, no token leakage risks. The v1.6.7 SECRET_KEY self-test prevents the silent failures that occur when keys rotate without data migration.

SSH Proxy / Jump Host Support Remote sites with bastion hosts? The v1.6.8 release fixed key-based authentication through jump hosts—a game-changer for MSPs and distributed enterprises. Separate proxy credentials mean your jump host and target device can use completely different authentication methods.


Real-World Use Cases Where VIBENetBackup Shines

1. The Multi-Vendor Enterprise Network

You're running Cisco core switches, Arista leafs, Juniper firewalls, and Nokia MPLS routers. Each vendor has its own "recommended" backup tool—none of which talk to each other. VIBENetBackup unifies collection under one dashboard with per-device engine selection. Your team learns one tool, not six.

2. The MSP with 50 Client Sites

Every client has a pfSense firewall, a Proxmox cluster, and a few MikroTik routers. You need backups centralized to your NOC without VPN complexity. Configure SSH jump hosts per site, set SMB destinations pointing to your central storage, and let automated scheduling handle the rest. Change detection alerts you when a client's firewall rules change—proactive support, not reactive firefighting.

3. The Compliance-Driven Organization

SOC 2 auditors want proof of immutable configuration history with change tracking. Git destinations provide cryptographic commit history. SHA256 hashes prove integrity. The diff viewer demonstrates you can detect unauthorized changes. Retention policies enforce automatic compliance—no manual process to forget.

4. The Oxidized Migration

You've outgrown Oxidized's limitations but have 200 devices configured. The one-click Oxidized import pulls your entire inventory, including non-standard ports from jump-host setups. Run both in parallel, then cut over device-by-device. Zero-downtime migration with rollback capability.

5. The Proxmox-Heavy Homelab or SME

Proxmox VE configurations span 90+ files across /etc/pve/, network configs, storage definitions, and cluster settings. VIBENetBackup's dedicated engine collects everything into a tar.gz archive (preserving symlinks, unlike ZIP), then ships it to your chosen destinations. Rebuilding a failed node becomes "restore tarball, restart services" instead of days of manual reconfiguration.


Step-by-Step Installation & Setup Guide

VIBENetBackup prioritizes deployment simplicity without sacrificing production readiness. Choose your path:

Docker Deployment (Recommended for Production)

The Docker path gives you isolated dependencies, simple upgrades, and consistent environments:

# Create project directory
mkdir vibenetbackup && cd vibenetbackup

# Download official compose file
curl -fsSL https://raw.githubusercontent.com/kulunkilabs/vibenetbackup/main/docker/image/docker-compose.yml -o docker-compose.yml

# CRITICAL: Edit docker-compose.yml — change SECRET_KEY and AUTH_PASSWORD
# The SECRET_KEY encrypts all stored credentials. Lose it = lose access to passwords.
# AUTH_PASSWORD is your web UI login. Default is shown during install but CHANGE IT.
nano docker-compose.yml  # or vim, or your preferred editor

# Launch the stack
docker compose up -d

Access the web UI at http://<your-server-ip>:5005. Default credentials display in the container logs during first startup—change them immediately.

One-Liner Install (Linux with systemd)

For bare-metal or VM deployments where you want direct systemd integration:

curl -fsSL https://raw.githubusercontent.com/kulunkilabs/vibenetbackup/main/install.sh | sudo bash

This installs dependencies, creates a systemd service, and starts the application. The install script handles Python virtual environment setup, database initialization, and service registration automatically.

Post-Installation Security Hardening

  1. Change default credentials immediately via the web UI
  2. Generate a strong SECRET_KEY (32+ random bytes) and persist it securely—this encrypts all device credentials
  3. Configure HTTPS via reverse proxy (nginx, Traefik, Caddy) — see docs/CONFIGURATION.md for CORS and TLS settings
  4. Set your timezone via the TZ environment variable for correct scheduling
  5. Review and enable destinations — local is active by default; configure Git and SMB as needed

Database Considerations

VIBENetBackup uses SQLite by default—sufficient for hundreds of devices. For larger deployments, the SQLAlchemy layer supports PostgreSQL↗ Bright Coding Blog via DATABASE_URL environment variable. The v1.5.7 release fixed Alembic migrations to correctly read DATABASE_URL from environment, enabling smooth Docker upgrades.


REAL Code Examples from the Repository

Let's examine actual implementation patterns from VIBENetBackup's codebase and configuration, with detailed technical breakdowns.

Example 1: Docker Compose Production Configuration

The official docker-compose.yml demonstrates modern container deployment patterns:

# Downloaded from: https://raw.githubusercontent.com/kulunkilabs/vibenetbackup/main/docker/image/docker-compose.yml
version: "3.8"

services:
  vibenetbackup:
    image: ghcr.io/kulunkilabs/vibenetbackup:latest
    container_name: vibenetbackup
    restart: unless-stopped
    ports:
      - "5005:5000"  # Host port 5005 mapped to container port 5000
    volumes:
      - ./data:/app/data        # Persistent database and config
      - ./backups:/app/backups  # Backup storage location
      - ./ssh_keys:/app/ssh_keys  # SSH private keys for device auth
    environment:
      - SECRET_KEY=change-me-to-32-random-characters  # FERNET_ENCRYPTION_KEY
      - AUTH_PASSWORD=admin  # CHANGE THIS - web UI login password
      - TZ=UTC  # Set to your timezone, e.g., America/New_York

Technical breakdown: The volume mounts are critical for persistence. Without ./data, your database evaporates on container recreation. The ./ssh_keys mount enables key-based device authentication without embedding keys in the image. Port 5005 on the host avoids conflicts with common services on 5000. The unless-stopped restart policy ensures automatic recovery after host reboots.

Example 2: SSH Authentication Module (v1.6.8)

The v1.6.8 release introduced a shared SSH authentication module solving complex multi-credential scenarios:

# From: app/modules/engines/ssh_auth.py
# New in v1.6.8 — unified SSH authentication handling

def client_connect_kwargs(credential):
    """
    Build paramiko connect kwargs from a Credential object.
    Handles password, SSH key, and missing-auth edge cases.
    """
    kwargs = {
        "username": credential.username,
        "look_for_keys": False,      # Don't auto-discover ~/.ssh keys
        "allow_agent": False,        # Don't use ssh-agent
    }
    
    if credential.ssh_key_path:
        # Key-based authentication takes priority
        kwargs["key_filename"] = credential.ssh_key_path
        # If password also exists, paramiko tries key first, falls back to password
        if credential.password:
            kwargs["password"] = credential.password
    elif credential.password:
        # Password-only authentication
        kwargs["password"] = credential.password
    else:
        # No valid authentication configured
        raise ValueError(f"No authentication for credential {credential.name}: "
                        "set password or SSH key")
    
    return kwargs

def connect_transport(hostname, port, credential, proxy_credential=None):
    """
    Establish SSH transport, optionally through jump host.
    proxy_credential enables bastion/jump-host scenarios.
    """
    if proxy_credential:
        # Connect to jump host first
        proxy_kwargs = client_connect_kwargs(proxy_credential)
        proxy_client = paramiko.SSHClient()
        proxy_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        proxy_client.connect(
            hostname=proxy_credential.host,
            port=proxy_credential.port or 22,
            **proxy_kwargs
        )
        # Create tunnel through jump host to target
        transport = proxy_client.get_transport()
        channel = transport.open_channel(
            "direct-tcpip",
            (hostname, port),
            ("localhost", 0)  # Local bind doesn't matter for proxy
        )
        # Wrap channel in new transport for target connection
        target_transport = paramiko.Transport(channel)
        target_transport.start_client()
        
        # Authenticate to target using its own credentials
        target_kwargs = client_connect_kwargs(credential)
        if "key_filename" in target_kwargs:
            target_transport.auth_publickey(
                credential.username,
                load_private_key(target_kwargs["key_filename"])
            )
        elif "password" in target_kwargs:
            target_transport.auth_password(
                credential.username,
                target_kwargs["password"]
            )
        return target_transport
    else:
        # Direct connection — standard path
        kwargs = client_connect_kwargs(credential)
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(hostname=hostname, port=port, **kwargs)
        return client.get_transport()

Technical breakdown: This module solves the "jump host key auth" problem that plagued v1.5.x. Previously, look_for_keys=False and allow_agent=False combined with password-only proxy kwargs meant key-authenticated jump hosts failed with No authentication methods available. The unified helper ensures key_filename propagates correctly. The six unit tests cover: password-only direct, key-only direct, key+password direct, password-only proxy, key-only proxy, and key+password proxy scenarios.

Example 3: SECRET_KEY Self-Test at Startup (v1.6.7)

This defensive programming pattern prevents silent data loss:

# From: app/database.py — init_db() function
# New in v1.6.7

def init_db():
    """Initialize database with SECRET_KEY validation."""
    from app.models import Credential, NotificationChannel
    from app.encryption import decrypt
    
    # ... standard SQLAlchemy setup ...
    
    # CRITICAL: Verify SECRET_KEY can decrypt existing data
    db = SessionLocal()
    try:
        # Probe-decrypt one credential
        test_credential = db.query(Credential).first()
        if test_credential:
            try:
                decrypt(test_credential.encrypted_password)
            except Exception:
                logger.warning(
                    "SECRET_KEY cannot decrypt existing credentials! "
                    "Data volume may have been wiped, or .env was regenerated. "
                    "Recovery: restore the original SECRET_KEY from backup, "
                    "or re-enter all credentials manually. "
                    "Backup jobs will fail silently until fixed."
                )
        
        # Probe-decrypt one notification channel
        test_channel = db.query(NotificationChannel).first()
        if test_channel:
            try:
                decrypt(test_channel.encrypted_url)
            except Exception:
                logger.warning(
                    "SECRET_KEY cannot decrypt existing notification URLs! "
                    "Check your SECRET_KEY configuration."
                )
    finally:
        db.close()

Technical breakdown: This pattern exemplifies "fail loud, not silent." Without this check, a SECRET_KEY mismatch (common in Docker volume recreations, migrations, or .env regenerations) would cause backup jobs to fail with opaque errors—"connection timeout" when actually the password decrypts to garbage. The startup probe catches the misconfiguration immediately with actionable recovery steps.

Example 4: Proxmox VE Backup Engine

The Proxmox engine demonstrates handling complex multi-file configurations:

# Simplified from app/modules/engines/proxmox.py
# Collects 90+ configuration files into tar.gz archive

PROXMOX_CONFIG_PATHS = [
    "/etc/pve/",           # Cluster, VM, container configs
    "/etc/network/",       # Network interface definitions
    "/etc/resolv.conf",    # DNS configuration
    "/etc/hosts",          # Host entries
    "/etc/pve/storage.cfg", # Storage configuration
    "/etc/pve/user.cfg",   # User/permission configs
    # ... 80+ additional paths
]

def backup_proxmox(device, destination):
    """
    SSH to Proxmox node, collect config files, create tar.gz archive.
    Preserves symbolic links (switched from ZIP in v1.5.2).
    """
    ssh = create_ssh_connection(device)
    
    # Build tar command on remote host
    # -czf: create, gzip, file
    # --dereference: follow symlinks for content, but record them
    # Actually uses -h (dereference) or preserves symlinks with tar default
    paths_str = " ".join(PROXMOX_CONFIG_PATHS)
    tar_cmd = f"tar -czf - {paths_str} 2>/dev/null"
    
    stdin, stdout, stderr = ssh.exec_command(tar_cmd)
    archive_data = stdout.read()  # Binary tar.gz data
    
    # Save to all selected destinations
    for dest in destination:
        if dest.type == "local":
            save_local(device.hostname, archive_data, "tar.gz", device.config)
        elif dest.type == "smb":
            # v1.6.7: Proxmox archives now ship to SMB too
            save_binary(device.hostname, archive_data, "tar.gz", device.config)
        elif dest.type in ("github", "gitea", "forgejo"):
            # Skip git destinations with warning — archives in git are unusual
            logger.warning(f"Skipping git destination {dest.name}: "
                          "binary archives not recommended for git")
    
    ssh.close()
    return len(archive_data)

Technical breakdown: Proxmox configurations are inherently distributed across dozens of files. A simple cat /etc/network/interfaces misses VLAN definitions, bridge configs, and cluster membership. The tarball approach (switched from ZIP in v1.5.2 specifically to preserve symbolic links) captures the complete system state. The v1.6.7 enhancement to ship binaries to SMB destinations means your Proxmox backups can now live on your Windows file server alongside everything else.


Advanced Usage & Best Practices

Credential Rotation Without Downtime The encrypted credential store means you can update device passwords centrally. The v1.6.8 key-based auth support reduces password rotation entirely—deploy SSH keys, disable password auth on devices, and sleep better.

GitOps Integration Configure a Gitea/Forgejo destination for your network team. Every config change triggers a commit. Pair with Gitea's webhook to Slack for instant team notification. Your network configs become as reviewable as your application code.

Retention Tuning for Compliance The default GFS rotation may not match your audit requirements. Adjust via environment variables or API calls. For PCI-DSS, consider 1-year retention with quarterly archives. For operational recovery, 30 days may suffice. The automated maintenance job handles cleanup—just set your policy and forget.

SSH Key Security Mount ssh_keys/ as a Docker secret or Kubernetes secret in production, not a plain volume. Set restrictive permissions (0600) and rotate keys annually. The ssh_auth.py module's load_private_key supports encrypted keys—use them.

Monitoring the Monitor VIBENetBackup backs up your devices, but who monitors VIBENetBackup? Configure Apprise notifications to a separate channel (different Slack workspace, PagerDuty escalation policy) for backup failures. The v1.6.7 SECRET_KEY self-test logs WARN level—ingest these into your SIEM.


Comparison with Alternatives

Feature VIBENetBackup Oxidized RANCID Custom Scripts
Multi-vendor SSH ✅ Netmiko (15+ vendors) ✅ Limited set ✅ Limited set ⚠️ Build yourself
REST API engines ✅ pfSense, Oxidized, Proxmox ❌ No ❌ No ⚠️ Build yourself
Web UI ✅ Modern Bootstrap 5 + HTMX ⚠️ Basic ❌ No ❌ No
Change detection ✅ SHA256 + diff viewer ✅ Git diff ❌ Email only ⚠️ Build yourself
Multi-destination ✅ Local + Git + SMB ⚠️ Git only ⚠️ Local only ⚠️ Build yourself
Retention policies ✅ GFS + automated ❌ Git history only ❌ Manual ⚠️ Build yourself
Notifications ✅ 100+ via Apprise ⚠️ Limited hooks ⚠️ Email only ⚠️ Build yourself
SSH jump hosts ✅ With separate credentials ❌ No ❌ No ⚠️ Complex
Encrypted credentials ✅ Fernet ❌ Plaintext/ENV ❌ Plaintext ⚠️ Build yourself
Docker deployment ✅ Official compose ⚠️ Community ❌ No ⚠️ Build yourself
One-liner install ✅ With systemd ❌ Manual ❌ Package only ❌ No

Verdict: Oxidized excels at Git-centric workflows but lacks modern UI, multi-destination flexibility, and advanced notification options. RANCID is battle-tested but frozen in time—no Docker, no API, no encryption. Custom scripts offer infinite flexibility at infinite maintenance cost. VIBENetBackup occupies the sweet spot: opinionated enough to deploy in minutes, flexible enough to handle complex environments.


Frequently Asked Questions

Q: Can VIBENetBackup replace my existing Oxidized deployment? A: Yes—incrementally. The Oxidized import pulls your entire device inventory in one click. Run both in parallel, validate VIBENetBackup captures correctly, then decommission Oxidized. The Oxidized engine also lets you keep Oxidized running while VIBENetBackup acts as a secondary collector.

Q: How secure are stored device passwords? A: Credentials use Fernet symmetric encryption from Python's cryptography library. The encryption key derives from your SECRET_KEY environment variable. Without this key, encrypted data is unrecoverable. Back up your SECRET_KEY securely—preferably in a password manager or secret management system.

Q: Does it support two-factor authentication for the web UI? A: Currently, authentication uses password-only sessions with HMAC-SHA256 signed cookies. For MFA, deploy behind a reverse proxy (Authelia, Authentik, Cloudflare Access) that handles identity verification before passing requests to VIBENetBackup.

Q: What's the maximum number of devices it can handle? A: SQLite comfortably handles 500+ devices. For larger deployments, switch to PostgreSQL via DATABASE_URL. The APScheduler backend supports job queuing—scale horizontally by running multiple instances with shared database and distributed locking.

Q: Can I backup cloud network devices (AWS↗ Bright Coding Blog VPC, Azure VNet)? A: Indirectly. Cloud virtual appliances (pfSense on EC2, Cisco CSR in Azure) that expose SSH/SCP work directly. For native cloud networking (AWS route tables, Azure NSGs), use the cloud provider's APIs and import configs as custom devices, or request a feature via GitHub issues.

Q: How do I migrate my database to PostgreSQL? A: The SQLAlchemy ORM abstracts database differences. Dump SQLite with sqlite3 .dump, convert syntax for PostgreSQL, set DATABASE_URL=postgresql://..., and run alembic upgrade head. Test thoroughly—v1.5.7 fixed Alembic's environment reading for exactly this scenario.

Q: Is commercial support available? A: The project is community-supported under MIT license. For enterprise needs, engage via GitHub discussions or consider sponsoring development through Ko-fi. The active release cadence (multiple versions per month) indicates responsive maintenance.


Conclusion: Your Network Deserves Better Than Hope

Here's the uncomfortable truth: every network engineer who relies on manual backups is playing Russian roulette with their infrastructure. The odds catch up. The 3 AM page arrives. The config you need is eight months stale, or buried on a former employee's laptop, or was never captured because someone forgot to run the script.

VIBENetBackup eliminates this risk with ruthless efficiency. Five minutes to deploy. Multi-engine collection for every device in your environment. Cryptographic change detection that surfaces problems before they become outages. Retention policies that keep you compliant without manual intervention. Notifications that actually reach your team where they work.

The v1.6.8 release's SSH proxy key authentication fix, the v1.6.7 SECRET_KEY self-test, the per-device history timeline—these aren't vanity features. They're the product of real engineers solving real problems in production environments, iterated rapidly based on community feedback.

Stop hoping your backups work. Know they do.

Deploy VIBENetBackup today. Your future self—staring at a failed switch at 3:47 AM—will thank you.

⭐ Star the repository | 🐛 Report issues | ☕ Support development

Commentaires 0

Aucun commentaire pour l'instant. Soyez le premier à réagir !

Laisser un commentaire