How I backup, restore and sync preferences and settings across computers.
Recently, I upgraded my Macbook at work but had to spend a few hours setting everything up again from scratch. This meant switching back and forth between both machines when the newer one was missing something I needed.
The weekend came around and I started exploring the different dotfile options available. GitHub has a curated list of dotfile tools I explored and eventually came to an approach I liked.
Things that I already I wanted to do were:
- Backup to Git
- Support for Mac and Linux
- No dependencies e.g. Python-based tool
- Ability to backup other things like npm, pip, brew
But the biggest thing I had to figure out was it better to copy or symlink the dotfiles...
Copying files vs Symlinking files
My first approach was 'copying' the files, as in every time there's a backup/restore, the files will be copied from the repository to their destination. There are some downsides to this:
- The repo is not always up to date
- Accidental deletion if 'restore' is run instead of 'backup'
- No constant 'single source of truth'
Symlinking on the other hand are like shortcuts/aliases to the original file. The downsides of symlinking on the other hand:
- Some applications may not like that files are links
- Moving symlinks may be troublesome i.e. the application does a migration
After trying both solutions, I decided on symlinks. The reason: I did the accidental deletion instead of a backup (downside #2)
Dotbot
After going through the curated list of dotfile tools, I landed on Dotbot by Anish Athalye.
Dotbot makes installing your dotfiles as easy as git clone $url && cd dotfiles && ./install, even on a freshly installed system!
Dotbot met all my requirements:
- Can be backed up to a Git repository. In fact, Dotbot is installed as a gitmodule so it can be easily updated, following the single source of truth philosophy
- After cloning my repo, I only have to run the install script to set everything up. Everything is managed in a single file
- It's a bash script without any other dependencies besides
git
andbash
- Other than symlinking dotfiles, it can also execute commands to trigger other custom scripts.
Custom scripts
Within the dotbot configuration, a shell section can be configured to specify commands to be executed. I use this for:
- Installing oh-my-zsh
- Installing brew and brew/cask packages
- Installing pip modules
- Installing npm packages
- Installing Vundle and its plugins
But before they can be installed, they need to be backed up. For that, I have written a backup script that triggers each of the above. It is not ideal but it's the only way this can be done. Set this to a cron schedule and you'll get a somewhat automated backup for them.