Version controlling server configuration with GIT

Often I want to version control certain, usually critical, system configuration files. In the past I’ve either set this up on a directory-by-directory basis or not bothered (which results in me creating a lot of superfluous files by doing a ‘cp config_file config_file.bak_`date +%F`’ before editing).

I, with a colleague, have come up with this solution that, while not necessarily perfect, is a lot more manageable then previous alternatives I have used and has the benefits of creating a centralised repository on a given machine as well as not polluting system directories with ‘.svn’ or ‘.git’ directories. It also avoids having to play with nested repositories (i.e. directories with a ‘.git’ dir under another that also has a ‘.git’ dir), which are unlikely if you’re just version controlling /etc but more common if controlling /home/$USER. I think it’s quite neat and keeps the revision control itself away from the core system files.

  1. The first step is to create a suitable directory to host the version control. We won’t actually be storing files here but it does need to be a “normal” repository (i.e. not a bare repository) as it does represent a working copy of the repository.

    mkdir /root/vc # Calling it 'vc' for 'Version Control'
    cd /root/vc

  2. Step two is to initialise our repository:

    git init

  3. Now, and this is the clever bit, we need to configure the repository to use ‘/’ as the base of it’s working tree (so we end up with a repository, with all it’s revision control files, in /root/vc but really the files under ‘/’ is under revision control). I also excluded everything by default (so git does not list everything as not being controlled and we can cherry pick the files we actually care about). UPDATE: I’ve since found the config variable ‘staus.showUntrackedFiles’ (reading man-pages FTW!), which achieves the same end in a much saner manner.

    git config core.worktree /
    echo '*' >> .git/info/exclude
    git config status.showUntrackedFiles no

…and that’s it. Just use the ‘/root/vc’ directory as a normal git repository but with any files under ‘/’. Simple, eh?

There is a drawback, however. Since I have excluded everything, files have to be added to the repository with a ‘-f’ (force) flag:

git add -f /etc/ssh/sshd_config

This also applies when using ‘git add’ to stage modified files however ‘git commit -a’, which stages modified & deleted files and commits in one step, does not required ‘-f’.
UPDATE: This is no longer an issue using ‘status.showUntrackedFiles’ to disable showing untracked files by default. There maybe other issues with this approach but I’ve not spotted them in my (5 minutes!) of testing/experimentation.

3 thoughts on “Version controlling server configuration with GIT”

  1. No, I really didn’t. Etckeeper still keeps its repository information (i.e. .git directory, if using git) in /etc and keeps everything in /etc under revision control. This solution allows you to not pollute /etc with revision control files, cherry pick files (e.g. only those which have been changed from the supplied versions) and keep more than just configuration files (e.g. on one server I’ve added a load of php files from /var/www to the same repository).

    I find that Puppet is horrendously slow to do anything (or, indeed, nothing – 3 minutes to run with a blank configuration file!), which is unacceptible in usecases where the machine might not be up for very long (e.g. multiboot desktops).

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>