This post is about how I wrote a fantastically useful script. If you have multiple computers, you will be thanking me by the end of it. Bold words, but what I’m going to describe here is that good.
The problem is that, like many of you, I have multiple computers. I have two desktops and two laptops (I just like keeping my old computers, they work), and installing a program on one was always a hassle, because I’d then have to remember to install it on the others and configure it the same way. Not only that, but, when I sometimes had to reformat (for performance, or to solve a problem, or whatever), I had to spend ages getting all the programs and their preferences working just the way I wanted them again.
I needed a better way to do this, and this is the post where I describe that way and how you can do it too. Here it is:
The solution actually consists of two steps. First, I need to create a git repository to hold the various preferences and assorted dotfiles in my home directory. The term “dotfiles” refers to the hidden files in each user’s home directory in UNIX, where programs store their preferences, settings, and other user-specific information. They are called that because they are hidden files, and hidden files in UNIX start with a dot. Storing them in a repository will allow me to save a history of all my application settings and sync them between computers by just pulling and merging. Programmers usually think git is the answer to everything, so this is very stereotypical of me.
The second step is to create a script to install programs and perform system-level tasks. This script will be stored in the repository above, for ease of use.
Of course, this entire solution kind of assumes you aren’t using Windows. If you are, I’m sorry, but at least you have AAA games available, so it’s not all bad.
A repository for dotfiles
Adding our dotfiles to a git repository is pretty simple, although there are helpers for you to get as fancy as you like. I’ve opted to just create a git repository in my home directory, which can sometimes cumbersome, so I would recommend that you pick a utility that suits your needs from the page above and go with it.
You should keep a few things in mind:
- Never run
git cleanon your home dir, as it will delete everything (your home is now a git repository, after all). Using one of the utilities above will help with this, since those don’t just turn everything into one huge repository.
- Be judicious in choosing which files you add to the repository. Don’t just add everything that’s in your home directory, or even most of it, because that will just require unnecessary commits and make your repository larger. It does take a bit more time to figure out where programs store their preferences, but it’s nothing you can’t find out in two minutes, and it will ensure you only sync the things you really need to.
- If some files contain sensitive information, you can use the excellent git-crypt to encrypt them with your GPG key. If you’re unfamiliar with GPG, here’s a [good introduction](https://www.madboa.com/geek/gpg-quickstart/), including details on how you can generate your key. This will ensure that nobody but you will be able to read the sensitive information (not even your git host), but be careful not to commit decrypted files, which can sometimes inadvertently happen.
After (some of) your dotfiles are sitting safely in a repository, all you need to do is remember to commit and push the changes every so often. When you switch computers, just git pull, and all your updated preferences will be available there as well!
We are now ready to proceed to phase “awesome”.
Writing a provisioning script
The role of the provisioning script is to bring the system into a specified state, from any starting state. This usually means using the system’s package manager to install packages, as well as checking if things are missing and only then installing them. The way I achieved this is with a series of small scripts, but you should feel free to use whatever tool you feel comfortable with. In my case, I used Ansible just because it’s very easy to write such a simple script, but anything else (even a simple and portable bash script) would work just as well.
The main script
First, let’s start with the main Ansible script: