While I was using macOS Server, keeping files on the server itself backed up was easy with Time Machine. I wanted a similar solution for my Ubuntu server: frequent incremental backups that “just work”.
This story is part of a series on migrating from macOS Server to Ubuntu Server.
You can find all of the other stories in the series here.
Finding a Tool
I came across a handful of tools for taking scheduled backups on Linux. A thread on Ask Ubuntu was particularly helpful in my quest. A handful of the tools listed there were more geared toward desktop users, but plenty of them were applicable to server users too.
After reading around for a little while, I decided on rsnapshot. It offers incremental backups using hard links, much like Time Machine. It’s also configurable enough for my needs, mainly the ability to pick directories to include/exclude in backups, and to configure backup schedule and retention.
Installation goes just like you’d expect:
sudo apt install rsnapshot
Configuration requires a little bit more explanation.
First, identify the directories you’d like to include in your backup. In my case, I want to back up
/media/LocalBackup. However, I’d like to exclude my Transmission download directory under
/media/Shares/Public since it changes often and I don’t care much about its content.
To deal with exclusions, first make a file in a directory higher up, in my case
/media/Shares/Public. The contents of the file should be formatted like
--exclude-from argument expects. Here’s how I set mine up:
sudo EDITOR /media/Shares/Public/server-backup-excludes
Public/0 Server Torrents
Follow that up with some permissions changes:
chown server:shares-access /media/Shares/Public/server-backup-excludes chmod 660 /media/Shares/Public/server-backup-excludes
Deciding Schedule and Retention
We’re almost ready to set up our
rsnapshot.conf file. We know what we want to backup, and where we want the backups stored. The next thing we need to figure out is what the schedule and retention should look like. Here’s what I decided to do:
|Time Period||Backups to Retain|
What this means is that when a 13th bihourly backup is going to be made, existing ones are incremented first, and the last bihourly becomes the first daily backup. That ripples through all of the other time periods, too.
If you want to learn more about how rsnapshot rotates backups, or you want to configure a different schedule, check out
man rsnapshot for more information about
retain and how it works. Note that
retain doesn’t actually schedule anything, it just gives you meaningful names for your backups.
rsnapshot Configuration File
Once you’ve decided on schedule and retention, it’s time to crack open the config file.
sudo EDITOR /etc/rsnapshot.conf
Note: While editing this file, you must use hard tab characters! You cannot copy directly from this post, I used spaces in my config snippets below.
We want to change a few things in here. I’ll start from the top.
First, set the directory where you want backups to live:
Check your system just to be sure, but I also had to uncomment a couple of lines:
cmd_du /usr/bin/du cmd_rsnapshot_diff /usr/bin/rsnapshot-diff
Next, set up your naming and retention. Here’s how mine looks:
retain hourly 12 retain daily 7 retain weekly 4 retain monthly 3
Then, set up your
rsync short args list. Here’s mine:
What do these args mean?
|Archive mode. This expands to |
|Preserve extended attributes|
I feel like these are pretty sane defaults, but you may want to look at
man rsync to see if there are other options you’d like to include. You can also find arguments you may want to include in
rsync_long_args as well. I left that option commented in my
Next, set up your exclude file, if you have one:
Last, configure what files you’re backing up. Here are the items that I have:
backup /media/Shares localhost/ backup /etc/ localhost/
There are a lot of other options available, so browse through the file to see if there are others you’d like to tweak.
Now, test your config:
# Check syntax sudo rsnapshot configtest # Test your first backup level, in my case `bihourly` # This will show the shell commands that would be run. Make sure it looks right sudo rsnapshot -t bihourly
As I mentioned earlier, this didn’t actually schedule anything, it just configured names for your backup levels.
This is the fun part! We’re going to make a systemd job for each backup level we defined in our config.
First, we’ll need a root service that all the scheduled jobs will call.
sudo EDITOR /lib/systemd/system/rsnapshot@.service
[Unit] Description=rsnapshot (%I) backup [Service] Type=oneshot Nice=10 ExecStart=/usr/bin/rsnapshot %I
This job is parameterized, and will call
rsnapshot with whatever comes after the
@ in the scheduled jobs.
Next are all my scheduled jobs. You will likely want to tweak the
OnCalendar1 parameter for your jobs to be at times that make sense for your system.
sudo EDITOR /lib/systemd/system/rsnapshot-monthly.timer
[Unit] Description=rsnapshot monthly backup [Timer] # The first of the month at 2 AM OnCalendar=*-*-01 02:00:00 Persistent=true Unitemail@example.com [Install] WantedBy=timers.target
sudo EDITOR /lib/systemd/system/rsnapshot-weekly.timer
[Unit] Description=rsnapshot weekly backup [Timer] # Sundays at 2:15 AM OnCalendar=Sun *-*-* 02:15:00 Persistent=true Unitfirstname.lastname@example.org [Install] WantedBy=timers.target
sudo EDITOR /lib/systemd/system/rsnapshot-daily.timer
[Unit] Description=rsnapshot daily backup [Timer] # Every day at 3:30 AM OnCalendar=*-*-* 03:30:00 Persistent=true Unitemail@example.com [Install] WantedBy=timers.target
sudo EDITOR /lib/systemd/system/rsnapshot-bihourly.timer
[Unit] Description=rsnapshot bihourly backup [Timer] # Every other hour at 45 minutes past the hour OnCalendar=0/2:45:00 Persistent=true Unitfirstname.lastname@example.org [Install] WantedBy=timers.target
Don’t enable these jobs yet! There’s one more thing to do.
Before we schedule our jobs, we need to take an initial backup. This may take a little while, so I recommend starting this in a
tmux session and detaching it so you can disconnect from the server while it goes.
# Start a backup for your first level, `bihourly` in my case sudo systemctl start rsnapshot@bihourly
Start and Enable the Timers
Once your initial backup is complete, all that’s left is to start and enable the systemd timers we made above.
sudo systemctl enable rsnapshot-bihourly.timer rsnapshot-daily.timer rsnapshot-weekly.timer rsnapshot-monthly.timer sudo systemctl start rsnapshot-bihourly.timer rsnapshot-daily.timer rsnapshot-weekly.timer rsnapshot-monthly.timer
At this point, you should have a “set and forget” backup solution for local files on your server. It’s pretty space-efficient, thanks to the use of hard links. Here’s how my disk usage looks for Shares and LocalBackup:
Filesystem Size Used Avail Use% Mounted on /dev/mapper/Shares--vg-Shares 3.6T 2.4T 1.1T 70% /media/Shares /dev/mapper/LocalBackup--vg-LocalBackup 3.6T 2.5T 955G 73% /media/LocalBackup
With that, I’ve also come to the end of explaining my replacement for macOS Server using Ubuntu. I accomplished most of my goals for replacing tools, with the exception of Caching Server, iTunes, and NetInstall. I’ve found that not having Caching Server hasn’t been a huge loss for me, and the same goes for NetInstall. I have iTunes set up on my Mac desktop, but I actually have the media library on the server to save space. This has been good enough for my needs.
Going forward, I’ll try to write more posts in this series that talk about new and useful things I add to my server, and changes I make as Apple deprecates things and when I run into problems.
Thanks for reading!
For more information on the syntax of
OnCalendar, check out
man systemd.time, section “Calendar Events” ↩︎