There are two types of digital nomads, those who have a single workhorse device and those who have several. This post covers the challenges faced by the latter type.
When I’m in the office I have a MacBook connected to a 34″ ultrawide monitor. This is where most of my work is done as it offers the best user experience. Lots of screen real estate, comfortable ergonomics, and perfect for long sessions. In the field, I have another MacBook that is a lot less enjoyable to use with it’s 13″ screen placed on random surfaces with the worst ergonomics and posture.
One of the challenges I face is synchronizing work in progress, ssh keys, and gpg keys between my devices. It’s been a problem for years and I’ve had several solutions, but none quite as elegant as Unison.
UNISON
I discovered Unison when looking for an option to synchronize WordPress data across several machines serving a very high traffic site. Normally we’d use an EFS volume or deploy an NFS server, but both of those weren’t options for that client.
Unison is described as:
Unison is a file-synchronization tool for OSX, Unix, and Windows. It allows two replicas of a collection of files and directories to be stored on different hosts (or different disks on the same host), modified separately, and then brought up to date by propagating the changes in each replica to the other.
As advertised, I can sync my devices before leaving the office and take all of my work in progress, ssh keys, and gpg keys with me in the field. Once I return, with a single command I sync all of my progress in the field back to my office computer.
1. INSTALL UNISON
This process will differ depending on your operating system / Linux Distribution. Unison has to be installed on all machines that will be synchronized. The machines do not have to be running the same operating system, but you’ll have to set your paths correctly. More details in the comments of the Unison profile.
MacOS: I prefer to use Homebrew. If you do not have Homebrew setup, run the ruby command in a terminal to install it.
# Only run this if you do not have Homebrew installed already.
# /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# Install unison via Homebrew (run as a user, not root).
rusted:~ vhillier$ brew install unison
Debian/Ubuntu: Packages are available in both official repositories and the snap store.
# If you want to install the official packages (the version tends to
# lag a bit).
vhillier@orsel:~$ sudo apt-get install unison
# If you want to install unison from the snap store (the version is
# or is close to the latest.
vhillier@orsel:~$ sudo snap install unison-jz
2. UNISON PROFILE
Unison can be run completely from the command line and it also supports “profiles”. A profile is simply a set of parameters in a configuration file so that we don’t have to type out long error prone commands to sync our data.
In this scenario, the profile lives on the office computer in ~/.unison/.prf. The mobile laptop does not have a profile and all synchronization events are triggered on the office computer. An example profile, we’ll call it laptop,prf, it below and should be copied to ~/.unison/laptop.prf. Things you’ll want to modify in this profile are potentially:
- servercmd This is the path to unison on the laptop.
- root The first root entry points to the directory on the office machine containing the data we want to sync. We’ll specify exactly what to sync with path directives below. The second root entry is where our defined paths will be synchronized on the laptop. You’ll want to change the IP and path no doubt, but take careful note of the double forward slash (//), it’s not a typo.
- path The path directives specify what files or directories within the root that we want to copy. As mentioned, I want my repositories, gpg keys, passwords, and ssh key data.
- backupdir Specifies the directory in which the sync backups will be stored. This is relative so that it can be the same on mixed environment deployments (MacOS/Linux). It will be located in the root specified above.
# Unison synchronization profile
# Bi-directional sync of office & field Laptop
#
# Vince Hillier <vince@revenni.com> 05/21/2019
#
# Debian installs unison with the following path. If unsure, run
# "which unison".
# servercmd=/usr/bin/unison
#
# Homebrew unison path
servercmd=/usr/local/bin/unison
# Roots
# Unison will sync the local root/$paths (see $paths below) to the
# remote 10.0.1.7. In my scenario, both are running MacOS. If the
# remote 10.0.1.7 were a linux machine, the root would be:
# root = ssh://10.0.1.7//home/vhillier/
root = /Users/vhillier/
root = ssh://10.0.1.7//Users/vhillier/
# Prefer allows the newer file to be synchronized.
prefer = newer
# Don't prompt us, just do the right thing.
batch = true
# Paths to keep synchronized. These are relative paths from the root
# defined above.
#
# I need my repositories from code, my gpg data from .gnupg, my
# password store from .password-store, and finally my ssh keys from
# .ssh.
path = code
path = .gnupg
path = .password-store
path = .ssh
# Ignore these files/paths
# ignore = Name temp.*
# ignore = Path */pilot/backup/Archive_*
# Don't copy gpg-agent sockets or vim .swp files.
ignore = Path .gnupg/S.*
ignore = Name *.swp
# Permissions should be retained.
owner = true
group = true
# Backups.
# Unison will store backups in a "central" location as defined by backupdir.
# You can opt for a 'local' backups which creates the backups in the directory
# wehere the sync happens, but that gets messy real quick.
backuplocation = central
backupdir = /Users/vhillier/.unisonbackups
# Backup file should have their original name prefixed with the $VERSION of the
# backup. Keep last 7 versions.
backup = Name *
backupprefix = $VERSION.
maxbackups = 7
# Generate a unison.log in the directory we invoke it in.
log = true
3. SYNCHRONIZE YOUR DATA
Before we synchronize your data there are a few things to note.
- Synchronization is always initiated by the office computer, even when the laptop has the most current data.
- Due to our prefer=newer setting, any files that exist on both the office computer and laptop machine will be replaced by the newest copy.
- In order to avoid potential overwrites, I suggest that the data only live on the office computer for the first synchronization, after that you can freely update content on either machine and be confident that Unison will update both of them with the newest files.
- We tell unison to load the profile we created by specifying it (minus the prf extension) as the first argument.
rusted:~ vhillier$ unison laptop