When I first created my VPS, I edited config files and made a note in a file in my home directory and that was it. If I were to ever move to a different VPS, then I would’ve copied over the notes file and all the files it mentions and set things up manually. Pragmatically, this is a perfectly acceptable setup given I have very little on my VPS and so far have only moved once in the 5 or so years I have been administering a server for. However, it has no form of version control and requires doing all the work through an ssh session which isn’t always desirable.
I recently came across this blog post
explaining how a post-receive
git hook can be used to automatically update a
website’s content when the repository is pushed to and decided to make some use
of it. Currently, I use a makefile rule like this to send my built site to my
VPS independently of pushing:
push: site
rsync --exclude-from=rsync-excludes -ruzv ./ user@host:/var/www/
This is what I am continuing to use as my website’s repository is not just static files, and it relies on a handful of more obscure and self-made tools. However, in the case of the VPS config files this can work perfectly.
I moved all those config files and things for my VPS into a private git
repository with a tree mirroring where they lie in my system. I also put the
notes in that repo so I always have them easily accessible, then I just have
this post-receive
hook (which goes in the hooks
directory of the bare git
repo on the server that’s being pushed to):
mkdir /tmp/vps
GIT_WORK_TREE=/tmp/vps git checkout -f main
sudo rsync --exclude-from=/tmp/vps/rsync-excludes -rv /tmp/vps/ /
git diff-tree --no-commit-id --name-only -r \
$(git rev-parse --verify HEAD) > /tmp/vps/modified
grep nginx.conf /tmp/vps/modified \
&& sudo systemctl restart nginx
rm -rf /tmp/vps
What this does is first create a temporary directory the tree can be checked out
to. Then it uses rsync
to apply the config files to the system. Next it gets a
list of all the files that were modified in the last commit and restarts
services if files relating to them were affected (in the example I’m just doing
this for nginx
, but in the real one I use it for several other files too).
Note that there is the caveat that you’ll need to allow the user running the git
commands (the one you’re pushing as) to run the systemctl
and rsync
commands
with sudo
without a password as they will not run interactively.
The result of this setup is I now have all my server’s config files version controlled, more easily accessible for tweaking, and a handful of menial tasks are automated for me!