Using git to track changes to /etc/config or entire /etc?

Hi
Is anyone have experience on tracking running config in git or similar? Done some quick tests manually grabbing backup generated via luci interface and storing it inside a repo. It make sense allowing me to roll back changes done if I did not like/mean it etc. though this manual process is not a working setup. Anyone got some thoughts on this?

1 Like

I have been doing this for years. Since I recently re-installed my router to current SW with DSA, I wanted to share how I do it.

Here are my requirements:

  • should be able to preserve file permissions and user/group group data
    rationale: Git only stores the executable-bit and no user/group info.
  • should manage all of /etc
    rationale: I want to be able to restore all changes after an upgrade, e.g. with
    # git reset --hard
  • should be managed by push-/pulling from PC, not from the router
    rationale: I don't want to open ports or install some server on my PC
  • should not occupy precious ROM on the router
  • should be easy to bootstrap after new firmware has been flashed to the router

For the file permissions and user/group data etckeeper would be the ideal solution. There was some effort to pack it, but unfortunately it is currently not in OpenWrt.
My workaround is to maintain an etckeeper-compatible /etc/.etckeeper manually.
It can be created (using findutils-find) with

# cd /etc
# find . -printf "maybe chmod %m '%p'\nmaybe chown %u '%p'\nmaybe chgrp %g '%p'\n"|grep -vE 'maybe (chown root|chgrp root)'>.etckeeper

Note: this must be committed before any potentially harmful Git operations.
After these took place, updates can then applied by a script which defines a maybe function (execute command only when file exists) and then sources .etckeeper.

For the other points my solution is an image file openwrt.img, which is

  • maintained and occasionally changed by root on the PC
  • scpd to/from /tmp on the router
  • loop-mounted on the router (to /mnt/img in my case) and has a subdirectory bind-mounted to /etc/.git

Image HOWTO (# is a shell prompt of root on the router, pc# on the PC)

Preparing the image file (mine currently has 24 MiB):

pc# dd if=/dev/zero of=openwrt.img bs=${SIZE}MiB count=1
pc# mkfs.ext4 -L $LABEL openwrt.img

pc# mount openwrt.img /mnt/openwrt
pc# pushd /mnt/openwrt
pc# mkdir -p root/.config/git
pc# pushd /mnt/openwrt/root
pc# echo 'alias etcmt='mount /tmp/openwrt.img /mnt/img && mount --bind /mnt/img/etc/.git /etc/.git'
alias etcum='umount /etc/.git && umount /mnt/img' > .profile
pc# touch .config/git/config
pc# git config --global user.name "Your Name"
pc# git config --global user.email "root@OpenWrt"
pc# git init
pc# git commit -a -m 'initial setup'
pc# popd
pc# mkdir -p /mnt/openwrt/etc/
pc# pushd /mnt/openwrt/etc
echo '*~
passwd-
shadow-
*.orig' > .gitignore
pc# git init
pc# git add .
pc# git commit -m 'initial setup'
pc# popd
pc# popd
pc# umount /mnt/openwrt

If the image is full:

pc# head -c $SIZE_INCREMENT /dev/zero >> openwrt.img
pc# resize2fs openwrt.img

Beware: use >>, > destroys your image!

A typical workflow is then

pc# scp openwrt.img 192.168.1.1:/tmp

# etcmt
# ### change files and commit

# etcum
pc# scp 192.168.1.1:/tmp/openwrt.img .

The initial bootstrap after the router has been flashed is

# mkdir /mnt/img
# mkdir ~/.git
# mkdir /etc/.git
# mount /tmp/openwrt.img /mnt/img
# mount --bind /mnt/openwrt/root/.git ~/.git
# cd ~
# git reset --hard
# umount .git
# . ~/.profile
# umount /mnt/img

To create proper history for /etc:

# tar -C /rom/etc cf /tmp/openwrt-etc-rom.tar .
# tar -C /etc cf /tmp/openwrt-etc.tar

pc# mount openwrt.img /mnt/openwrt
pc# pushd /mnt/openwrt/etc
pc# git reset --hard
pc# scp 192.168.1.1:/tmp/openwrt-etc-rom.tar /tmp
pc# scp 192.168.1.1:/tmp/openwrt-etc.tar /tmp
pc#  git checkout $THE_INITIAL_SETUP_COMMIT
pc# rm -rf *
pc# tar xf /tmp/openwrt-etc-rom.tar
pc# git add .
pc# git commit -m 'new firmware <FW_FILE_NAME>, content of /rom/etc'
pc# rm -rf *
pc# tar xf /tmp/openwrt-etc.tar
pc# git add . -A
pc# git commit -m 'content of /etc after reboot and first login'
pc# popd
pc# umount /mnt/openwrt

Beware: before you start changes in /etc on the router after there where commits in
/mnt/openwrt/etc on the PC or changes in /mnt/openwrt/etc after there were commits in /etc on the router you MUST do a git reset --hard to sync the files in the /etc directories with the state in .git.
Be especially carefully if you switched branches!

1 Like