Back in the day1 when I was still using a Mac, I always enjoyed the simplicity of Time Machine backups that Apple introduced almost 20 years ago. Simply plug in your dedicated drive, let Time Machine do its thing and hey presto, snapshots of your precious data. My wife’s MacBook Pro from 2013 is still backing up to a Drobo 5N of a similar vintage over SMB to this day.
I tend to synchronise my important folders such as documents, photos and videos via
Syncthing and that works without issue. However, I also have a large
~/Development folder that I don’t synchronise. To a degree this is due to the fact that I push
most source code I care about to GitHub or Codeberg.
I also had bad experiences with Dropbox in the past where its synchronisation mechanism would
get confused with operations in the .git folder across multiple hosts. And because of that
experience, I never used to back up my Development folder, which was a shame, really.
So the other day, while I was looking at a disused 256 GB drive lying around on my desk, a thought popped up in my head. What if I asked Clyde2 to whip up something real quick in that regard, with the following constraints3:
- It should run when I plug in an external drive
- It should run as a non-privileged process
- It should eject the drive when it is done
- It should have an easy to understand config file
- It should use
rsync - It should use hard links like the original Time Machine
Lo and behold, a little prompting later, I got my first version. It worked flawlessly on the
first try and backed up my 87 GB worth of stuff in under 10 minutes. At first, the process
was silent, so I didn’t know what was going on, but I then remembered that my flavour of
Linux comes with notify-send which made it simple to add toast notifications to my desktop,
telling me what was going on.
The beauty of the solution is that you can simply browse the snapshots on disk as a file tree. No special format, no index database. Just files! Thanks to hard links, each snapshot looks like a full backup, but only files that changed since the last one take up extra space.
How it works
systemdtracks every block device as a device unit- when a drive is plugged in,
udevcreates/dev/disk/by-uuid/<UUID>whichsystemdturns into a<device>unit - the install script adds a
~/.config/systemd/user/<device>.wants/rsync-snapshot.servicesymlink that triggers the service when the drive is plugged in - the backup script handles the mounting and unmounting of the drive
Here’s a little demo of it working:
Check out its code: codeberg.org/tsak/rsync-snapshot
It comes with an extensive README.
Or you can just follow the install instructions (after you’ve cloned its repository):
-
Install:
./install.shOn the first run this creates
~/.config/rsync-snapshot/configwith an emptyUUIDand stops before setting up the plug-in trigger, listing the attached drives so you can pick yours (same aslsblk -f). -
Edit
~/.config/rsync-snapshot/config: setUUIDand list the folders to back up inSOURCES:UUID="2155b0cb-13a2-452b-a336-f3a309f79b63" SOURCES=( ~/Documents ~/Pictures ~/Development ) EXCLUDES=( .cache/ node_modules/ ) -
Run
./install.shagain. WithUUIDset it enables the trigger. Do the same whenever you changeUUIDlater, so the trigger follows the new drive.
Footnotes
1 I started using Linux full-time in 2018. These days I use just a bunch of scripts on top of Arch Omarchy btw
2 Naming it Claude instead was a missed opportunity on Anthropic’s part in my opinion
3 The real discussion went a little differently. I asked Clyde about how to get a similar
experience to Time Machine on Linux and it suggested restic or borg - the complexities of each
were not what I was longing for in my fond memories of Time Machine