Skip to content
Client Panel

Configuration Backup with Git

Every VyOS commit can trigger a script. This guide sets up a post-commit hook that exports your config, commits it to a local Git repo, and pushes to a remote — giving you full version history of every router change.

Based on brav0charlie’s workflow (original blog offline, preserved via Wayback Machine). Adapted for VyOS 1.4+.

VyOS Router Git Server (Gitea/GitHub/GitLab)
┌──────────────────────────┐ ┌─────────────────────┐
│ commit │ │ │
│ ↓ │ │ config-router01/ │
│ post-hook script: │ push │ ├── router01 │
│ 1. export config │────────▶│ │ .commands.conf │
│ 2. git add -A │ │ │ .config.boot │
│ 3. git commit │ │ └── ... │
│ 4. git push │ │ │
└──────────────────────────┘ └─────────────────────┘

The default VyOS ISO does not include Git. You have two options:

  1. Build a custom image with Git included (see Image Automation)
  2. Install Git on a running system (won’t survive upgrades):
Terminal window
# Temporary — lost on reboot/upgrade
sudo apt update && sudo apt install -y git

Preferred: build a custom image. One-time effort, permanent result.

So your router can push to the remote without storing keys on it:

Terminal window
# ~/.ssh/config on your LOCAL machine
Host vyos-router
HostName 192.168.1.1
User admin
ForwardAgent yes

Create a private repository. Never make router configs public — they contain secrets, keys, and network topology.

Recommended: self-hosted Gitea in Docker, or private GitHub/GitLab repo.

Terminal window
# Log into VyOS, set Git identity
git config --global user.name "VyOS Router"
git config --global user.email "[email protected]"
# Clone into persistent storage
cd /config/user-data
git clone [email protected]:infra/config-router01.git

/config/user-data persists across reboots and upgrades. Everything else in / is ephemeral.

Terminal window
sudo mkdir -p /config/scripts/commit/post-hooks.d
sudo nano /config/scripts/commit/post-hooks.d/99-git-commit

Paste the script:

/config/scripts/commit/post-hooks.d/99-git-commit
#!/bin/vbash
# Post-commit hook: export config, commit to git, push
REPO_PATH=/config/user-data
CONFIG_REPO=config-router01 # <-- change this
TIMESTAMP="$(date '+%Y-%m-%dT%H:%M:%S %Z')"
# Commit message — set env var $M for custom message
# Usage: M="added VLAN 20" commit;save
if [ -z "$M" ]; then
MSG="Auto-commit by $USER@$HOSTNAME: $TIMESTAMP"
else
MSG="$M"
fi
# Source VyOS script functions
source /opt/vyatta/etc/functions/script-template
USERPATH=$PWD
cd $REPO_PATH/$CONFIG_REPO
echo "> [$TIMESTAMP] Beginning git commit & push..."
# Pull latest
/usr/bin/git pull
# Export config in two formats
run show configuration commands > $REPO_PATH/$CONFIG_REPO/$HOSTNAME.commands.conf
run show configuration commands json > $REPO_PATH/$CONFIG_REPO/$HOSTNAME.config.json
# Git workflow
/usr/bin/git add -A
/usr/bin/git commit -m "$MSG"
/usr/bin/git push
echo "> [$TIMESTAMP] Git commit & push completed."
cd $USERPATH
# Clean up
CONFIG_REPO=""
REPO_PATH=""
TIMESTAMP=""
USERPATH=""
MSG=""
M=""
Terminal window
sudo chmod +x /config/scripts/commit/post-hooks.d/99-git-commit

Every commit now triggers the backup:

Terminal window
configure
set system host-name vyos-gw-new
commit
save
# → Script runs, pushes config to Git

Custom commit message:

Terminal window
# Set $M before commit
M="Changed WAN DNS to Cloudflare" commit;save

Two files per commit in your repo:

FileContent
hostname.commands.confFull config as set commands — human-readable, diffable
hostname.config.jsonFull config as JSON — machine-parseable
Terminal window
# View history
git log --oneline
# See what changed
git diff HEAD~1 hostname.commands.conf
# Restore a previous config
git show abc1234:hostname.commands.conf

If your router dies, restore the config to a fresh VyOS install:

Terminal window
# On new VyOS
cd /config/user-data
git clone [email protected]:infra/config-router01.git
cd config-router01
# Load saved config
configure
load hostname.commands.conf
commit
save

If you prefer manual control, skip the hook and run on-demand:

/config/scripts/backup-config.sh
cd /config/user-data/config-router01
run show configuration commands > $(hostname).commands.conf
run show configuration commands json > $(hostname).config.json
git add -A
git commit -m "Manual backup $(date -Iseconds)"
git push

Run it: source /config/scripts/backup-config.sh

If you must use a less-private repo, filter secrets before commit:

Terminal window
# Add before git add in post-hook
sed -i '/plaintext-password/d' $HOSTNAME.commands.conf
sed -i '/pre-shared-secret/d' $HOSTNAME.commands.conf
sed -i '/private-key/d' $HOSTNAME.commands.conf

Better: use a private self-hosted repo and don’t sanitize — you want the full config for disaster recovery.

Terminal window
# Check hook is in place
ls -la /config/scripts/commit/post-hooks.d/
# Test manually
sudo /config/scripts/commit/post-hooks.d/99-git-commit
# Check Git status
cd /config/user-data/config-router01
git log --oneline -5
StepCommand
Build image with Git--custom-package git (see image automation guide)
Clone repocd /config/user-data && git clone <url>
Create hook/config/scripts/commit/post-hooks.d/99-git-commit
Usecommit;save — backed up automatically
Custom messageM="description" commit;save