🍵️

2021-01-04

Simple Incremental Backup With Rsync

I've been on the search for the "perfect" backup solution for a long time -- a search that never ends, because the target is so elusive. Basically the perfect backup is local + offsite, encrypted, incremental (but also full!), withstands bit rot, is not with a commercial cloud vendor, and for some reason that I can't really articulate it isn't Borg Backup either (actually it probably is; Borg Backup seems f***ing awesome, but for some reason I just can't get excited about it).

Borg Deduplicating Archiver With Compression and Encryption

For now I don't even have an offsite backup (shame on me), but I like the simplicity of my local backup. It's really just a small trick with rsync+cp that I picked up at a previous workplace.

It's executed once a week by cron (because I keep mixing cron and systemd.timers for no good reason):

$ cat /etc/cron.d/weekly-backup 
# Take an incremental backup of users home directories every Sunday at 5am
0 5 * * 0 root incremental-backup 

And the script itself is very short and sweet (for reference /mnt/usb1/users is mounted as /home and /mnt/usb2 is my backup disk):

$ cat /bin/incremental-backup
#!/bin/bash

SOURCE=/mnt/usb1/users
DESTDIR=/mnt/usb2
DEST="${DESTDIR}/latest"

mkdir -p "${DEST}"

rsync --archive --delete --verbose "${SOURCE}" "${DEST}" > "${DEST}/backuplog"

cp -prl "${DEST}" "${DESTDIR}/$(date --iso-8601=minutes)"

The last two commands do the trick. The first rsyncs to a dir called "latest" (which doesn't need to be created which mkdir every time... there is room for improvement even here), keeping ownership and deleting files in the destination directory which have been deleted in the source. This is incremental, and only pushes changes since last backup.

The second command copies the directory "latest" to another directory named as a timestamp. Note the flags:

For each backup I get a directory tree that is a full backup of /home, but it only takes as much room as the changes since last time.

Check it out:

root : usb2 $ du -csh * | sort -k 2
66G     2020-08-16T05:00+02:00
15M     2020-08-23T05:00+02:00
16M     2020-08-30T05:00+02:00
78M     2020-09-06T05:00+02:00
17M     2020-09-13T05:00+02:00
2.9G    2020-09-20T05:04+02:00
304M    2020-09-27T05:00+02:00
260M    2020-10-04T05:00+02:00
1.2G    2020-10-11T05:02+02:00
1.2G    2020-10-18T05:02+02:00
794M    2020-10-25T05:02+01:00
27M     2020-11-01T05:00+01:00
24M     2020-11-08T05:00+01:00
24M     2020-11-15T05:00+01:00
24M     2020-11-22T05:00+01:00
56M     2020-11-29T05:00+01:00
27M     2020-12-06T05:00+01:00
90M     2020-12-13T05:00+01:00
39M     2020-12-20T05:00+01:00
33M     2020-12-27T05:00+01:00
3.5G    2021-01-03T05:05+01:00
24M     latest
16K     lost+found
76G     total

-- CC0 Björn Wärmedal