While there are many cloud backup solutions available for Windows computers, and even some Mac and Linux devices as well, I found that there weren’t many ready-made tools or scripts to handle backing up a Linux server to a local disk. Running a headless (non-GUI) Slackware server for file storage and web hosting, I decided to take some of the ideas others had and combine them into a script that will ensure incremental as well as full-volume backups, without requiring tons of disk space.

First, the script:

#!/bin/bash

date=`date "+%Y-%m-%d"`
rsync -aP --link-dest=/mnt/external/current \
     --include={[explicit include subdirectories]} \
     --exclude={[explicitly excluded directories]} \
     /* /mnt/external/backup-$date

rm -f /mnt/external/current
ln -s backup-$date /mnt/external/current

In general, what this script does is take a copy of everything on my server, excluding what is in particular, specified directories, and add them to my external drive under a date-stamped directory. If any of those files already exist and are unchanged from the previous backup, instead of copying them all over again, it creates a hard file link instead. The most recent backup set is always available as “current” and folders are named with the date the script ran.

These days I’m backing up about 300gb of data, and keep 10 full, complete copies of my data on a single 1TB drive, currently at <50% capacity. Due to how hard links work, this saves an amazing amount of space even while giving me full file-level access to every backup set.

While I have no doubt I could simplify or otherwise streamline the script, it works very well for my needs right now and is robust enough to run unattended on a given schedule. I can delete old backup sets without worrying about deleting files contained in newer sets, and make sure that every file is kept up to date.

I want to touch on the inclusion of both —include= and –exclude= flags. The latter details a specific list of directories not to back up, and in my script I include things like /dev and /proc as well as a rather significant music collection. The –include directive overrides the exclude, so for example if I didn’t want to backup all of /music/techno/ but I really wanted to keep a copy of anything in /music/techno/my_mixes/, with a combination of the include and exclude flags, I can tailor  the script to backup exactly what files I want.

If anyone has more questions about how the script works or how it can be customized for their specific environment, please feel free to email me!