Putting My Life in Version Control Part 1: Linux Config Files

In this article I will describe how I setup a central repository to store my configuration files and shell scripts, and a quick process to bring new computers into the system and continue propagating configuration changes as I make them. To use the centralized repository approach, you need to have an account on a file/shell account server somewhere that’s online at least most of the time.

I have about three and a half Linux hosts that I use on at least a semi-regular basis, depending on how you count:

Since virtually all apps in Linux store their per-user configuration information in text files and scripts somewhere under ~ (your home folder), it would be nice to share and synchronize that information across all my Linux hosts. For example, if I find the right Greasemonkey (user Javascript) script that solves a web site shortcoming, or write a shell script to get automate some task, I don’t want to be replicating that effort on each host. Nor should I have to manually synchronize all this stuff once I’ve configured it right in any one place.

For this project, I wanted to learn how to use the Bazaar version control system. I have much experience with Subversion at work and personally, keeping my office projects and personal notebooks in Subversion repositories, but I find Subversion takes more time than I’d like to perform a synchronization. Bazaar has some neato features that appeal even to people who are working on personal data and not collaborating, such as easier merging of parallel changes (compared to Subversion) and offline commits. Other next-generation distributed version control systems improve upon Subversion’s non-distributed architecture, but my casual research shows that Bazaar is one of the more newbie-friendly choices. Your mileage may vary.

Step 1: Initialize your repository

On the central SERVER:

mkdir ~/etc/config
cd ~/etc/config
bzr init
bzr checkout

Step 2: Move config files into into the repository

My concept is to keep all shared configuration files under ~/etc/config/PATH/FILE where PATH is the original path under ~ and FILE[/file] is the file name. This makes it easy to keep only the shared files in your Bazaar repository while ignoring all other config and data files.

mkdir ~/etc/config/etc
mv ~/etc/brendan.jpg ~/etc/config/etc/ # profile photo for social web sites
mv ~/etc/buddy-icon* ~/etc/config/etc/ # IM buddy icon (various formats)
mkdir ~/etc/config/bin
mv ~/bin/mount-* ~/etc/config/bin/
mv ~/bin/weather ~/etc/config/bin/
mv ~/bin/mailpda ~/etc/config/bin/
mkdir ~/etc/config/.config
mkdir ~/etc/config/.config/fish # Fish is my chosen command line shell
mv ~/.config/fish/config.fish ~/etc/config/.config/fish/
mkdir ~/etc/config/.config/fish/functions
mv ~/.config/fish/functions/* ~/etc/config/.config/functions/
mkdir ~/etc/config/.config/Terminal # XFCE Terminal
mv ~/etc/.config/Terminal/terminalrc ~/etc/config/.config/Terminal
# et cetera!

I hope you get the idea.

Of course you need to access these files in their original locations. Linux’s symbolic links come in really handy here. (Why does Windows still not have symlinks? :^( )

Filename: ~/etc/config/bin/install-shared-config

#!/usr/bin/fish
# install-shared-config
#
# This script installs links to ~/... from ~/etc/config/..., which is
# kept in version control.
 
# You'll need fish <http://www.fishshell.org/> to run this script
# -- or translate it into bash if you wish.
 
cd $HOME/etc/config
for i in (find . -not -path "./.bzr*" -type f -printf "%Pn")
   set d (dirname $i)
   echo $i
   mkdir --parents "$HOME/$d"
   ln --symbolic "$HOME/etc/config/$i" "$HOME/$i" 2>/dev/null
end

# make the script executable
chmod +x ~/etc/config/bin/install-shared-config

Then run the script and all your shared files will once again be available from their original locations.

Step 4: Check in your shared files

cd ~/etc/config
bzr add
bzr commit -m "Initial checkin"

Checking out the files on a remote host

Here’s how you add another host to the system — your laptop that you do most of your work on, for example:

mkdir ~/etc/config
cd ~/etc/config
bzr checkout bzr+ssh://USERNAME@SERVER/home/USERNAME/etc/config .
 
# Manually remove any already-local copies of config files found in
# the shared repository. The install script doesn't do this for you!
 
~/etc/config/bin/install-shared-config

Syncing a remote host

cd ~/etc/config
 
# Download upstream changes
bzr update
 
# What's new locally?
bzr stat
 
# Did you add new files since the last checkin? Run this to add all new files:
bzr add
 
# Did you rename files since your last checkin?...
bzr mv OLDNAME NEWNAME
 
# Did you delete files?...
bzr rm DEADFILE
 
# Done!
bzr commit -m "SUMMARY OF CHANGES"

Some notes about Opera web browser

Be careful what you put into your version control repository. For example, ~/.opera/opera6.ini would be problematic for at least two reasons: my username is embedded in it (my username is not consistent from one host to another), and transient stuff like window positions and recently used files are stored in it. I think it’s best to recreate my Opera configuration individually on each host.

The parts of Opera I do keep in version control are my user style sheet and my user javascript files.

I have a CSS file in ~/etc/user.css (which is a symlink to ~/etc/config/etc/user.css of course) that adds a thin yellow border around all links instead of whatever the site designer chose, so I can’t miss links. This file is installed using the Opera setting UserPrefs|LocalCSSFile.

And my collection of user Javascript files are in ~/etc/userscripts and installed using the Opera setting UserPrefs|UserJavaScriptFile.

Other applications you use might require similar specific tweaking.

More to come?

I’m just getting used to Bazaar for now, and my config files are a good low-risk data set to play around with. In the future, I will probably transition my Zim notebooks from Subversion to Bazaar and document it here. Using Bazaar should make it relatively easy to store an encrypted backup of my Notebooks repository on some public host, and keep it up today with a daily cron job; this way I will always have access to an up-to-date copy in case I’m on a host that is terribly out of sync — even if my main file server is offline!

Leave a Reply

Please view the Comment Policy before submitting a comment.
 

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