Encrypted, Rotating Time Machine Backups on Snow Leopard

Changes in 10.6.5

Unfortunatley, things have changed in 10.6.5, and I haven’t quite determined how to correct the automatic rotation part of this article. However, there are some workarounds in the comments

I like Time Machine. It’s automatic, incremental, efficient and easy to use. However, there are two features that Time Machine doesn’t have that I really like: encryption and rotation (for offsite backup). With the help of others, along with a bit of hacking around on my own, I’ve successfully enabled Time Machine to backup to an unlimited amount of rotating, encrypted hard disks. Here’s how…

Creating the Disk Image

When you use Time Machine to backup over the network to a Time Capsule or an OS X Server, Time Machine creates a disk image on that volume, and mounts that disk image, and backs up to the image. By using an image, Time Machine doesn’t have to worry about the permissions or configuration of the remote volume. Unfortunately, when Time Machine creates this image, it gives you no option to encrypt it, which disk images support, but that’s OK. We can create it ourselves.

First, note the name of the computer you are backing up in the Sharing pane of System Preferences:

System Preferences Sharing Pane

This will be the name you give your disk image. In my case, there are no spaces or non-alphanumeric characters in my computer’s name. I recommend doing the same as I’m unsure if anything beyond that might cause an adverse reaction.

Next, open Disk Utility and create a New Blank Disk Image (File -> New -> Blank Disk Image):

New Black Disk Image

Note the relevant parameters:

  • Name: Time Machine Backups
  • Size: Choose an appropriate custom size for your disk image. This is the maximum amount of storage space you want to dedicate to backups. Make sure this is at least 1% smaller than the backup drive(s) on which you’re going to be storing it.
  • Format: Mac OS Extended (Journaled)
  • Encryption: There are two different types, exchanging performance for security. I opt for the more secure flavor.
  • Partitions: Single partition. I’m in the habit of choosing Apple Partition Map for a PowerPC Mac and GUID Partition Map for an Intel Mac, but it shouldn’t make any difference.
  • Image Format: sparse bundle disk image

Custom SizeBe warned that in the custom size sheet, if you enter an amount before changing the unit and then change the unit, your amount will be lost, so change the unit first.

Save the image on to your backup drive, making sure to not place it in any folder. You will be prompted to enter the new disk image’s password twice and you will have the option to store it in your keychain. Make sure you do! The image should automatically mount as Time Machine Backups on your desktop. If you don’t see it, you might want to make sure External Disks are configured to be Shown on the desktop in Finder’s Preferences:

Finder Preferences

Eject it.

Enable Automatic Mounting

We need to let the system know the disk image’s password so it back up to it unattended. To facilitate this, we need to add it to the System keychain.

In the Utilities folder, in your Applications folder, open Keychain Access.app. Make sure you can see a list of available Keychains in the top left, e.g. login and System. If not, go to the view menu and choose Show Keychains. In the main section of the window, you should see an entry named after your disk image, i.e. ComputerName.sparesbundle. Drag the ComputerName.sparsebundle entry from the list to the System keychain in the top left:

Keychain Access

After releasing, you will be prompted to enter an administrator username and password. Time Machine can now backup to your disk image without your intervention.

Add Time Machine support to your disk image

A tip of my hat to this article on Mac OS X Hints, on configuring Time Machine to backup to a remote volume, for showing me how to alter the image so that Time Machine correctly sees it as a proper backup destination.

To start, you will need your computer’s UUID. Open System Profiler and in the default screen, it should be visible for you to highlight an copy:

System Profiler UUID

Now, in a competent text editor, create a new file with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.backupd.HostUUID</key>
    <string>YOUR-UUID-HERE</string>
</dict>
</plist>

It’s hopefully quite obvious, but make sure to replace YOUR-UUID-HERE with the actual UUID you gathered from the System Profiler window.

Save this file, naming it com.apple.TimeMachine.MachineID.plist.

Now, you need to copy this file INSIDE the disk image package (not the disk image volume). What do I mean by that? Well, your disk image should be named something like ComputerName.sparsebundle. If you don’t see the .sparsebundle part, you might also want to make sure that “Show all filename extensions” is enabled in the Finder’s Preferences:

Finder Preferences

A .sparsebundle is what OS X calls a package. In reality, it’s actually a folder, with contents, but the fact it is a folder is hidden from the user. Right-click on the file (or control-click if you don’t have a 2 button mouse) and choose “Show Package Contents”:

Show Package Contents

In the resulting window you should see the files and folders that make up a .sparsebundle. Copy or move your com.apple.TimeMachine.MachineID.plist into that directory, so it should look like this:

Disk Image Package Contents

You can now close this window. Your disk image is ready!

Configuring Time Machine

In essence, the steps we have taken above are the same steps Time Machine automatically takes when backing up to a network volume for the first time (without the encryption of course). There’s a great little “feature” which I believe Apple enabled in order to assist users with doing their first large backup after configuring a Time Capsule, and that’s the ability to take the drive attached to a Time Capsule (after such a disk image has been created), plug it directly into one of the Mac’s that backs up to it, and that Mac will still backup to that disk image, rather than just backing up to the Backups.backupd directory as a directly connected Time Machine installation would. It is this feature that makes local backups to an encrypted disk image possible.

Note that even in this situation, Time Machine will still create the Backups.backupd directory if it doesn’t exist, but if all has gone well, it should have no contents.

So, let’s review what we should have in place:

  1. An external disk connected.
  2. A self-created, encryped sparse bundle disk image located on that disk, named after the computer it’s connected to. The image should not be mounted.
  3. A file named com.apple.TimeMachine.MachineID.plist containing our computer’s UUID located inside the disk image.

If that’s all in place, let’s open System Preferences, go to Time Machine and select the Backup drive (not the image). A countdown timer should count down for 120 seconds before it starts its first backup. You can preempt it by choosing Backup Now from the menu bar, assuming you have checked “Show Time Machine status in the menu bar”. If everything has gone well, the first status message should say “Mounting backup disk image” and the Time Machine Backups volume should automatically appear on the desktop and the backup should start thereafter. Make sure that no files are appearing inside the Backups.backupd directory on the backup disk. If there are, it likely means that Time Machine is backing up to that directory instead of the disk image due to something not being correctly configured. If that’s the case, please reread all of the above to ensure you didn’t miss a step.

Preparing the additional backup drives.

There was a great article on Curmi The Blog that I followed in order to create rotating backups for Leopard Server. It involved ensuring that a hidden file identifying the backup drive was cloned over to any rotated backup drives in order to trick Time Machine into believing they were all the same drive. Hoping this would still work, I used the amazing SuperDuper! to clone my backup drive to another backup drive (making sure Time Machine was not running and the disk image was not mounted when doing so).

However, Curmi’s method didn’t work under Snow Leopard and that identifying file was not present. Thus, I had to write a script to inform Time Machine that the backup drive had been rotate, so I’m not sure using SuperDuper! is necessary, but it certainly won’t hurt. If you’d like to try without it, simply copy your image, ComputerName.sparsebundle, to your additional backup drives.

You can now test by manually rotating the backup drive. Safely eject the first drive and connect the second drive, then choose that drive in Time Machine’s settings in System Preferences. The countdown timer should begin again and Time Machine should backup to the additional backup drive, picking up from where the disk image left off.

Automating the backup drive rotation

THIS ONLY WORKS FOR 10.6.4 AND EARLIER. UPDATE TO COME SHORTLY

I searched around for how to get Time Machine to automatically backup to the additional drives and none of the solutions were as seamless as Curmi’s. I found some scripts that used AppleScript interface scripting to click around the options in System Preferences to choose the secondary drive. I’m not a big fan of interface scripting, so I wrote a more silent shell script, supporting unlimited drives, requiring no third party software, that could work without anyone being logged in.

This script expects that each rotating backup drive will have the same name, and that name is “Backup HD”. Using a competent text editor, create a new file with the following contents:

#!/bin/sh
mountedDisk=`diskutil info "Backup HD" | awk '/UUID/ {print $3}'`;
if test $mountedDisk
    then
    echo "Mounted Disk UUID: $mountedDisk";
    configuredDisk=`defaults read /Library/Preferences/com.apple.TimeMachine DestinationVolumeUUID`;
    echo "Configured Disk UUID: $configuredDisk";
    if test $mountedDisk = $configuredDisk
        then
        echo "Configuration is correct."
    else
        echo "Configuration requires update. Updating..."
        defaults write /Library/Preferences/com.apple.TimeMachine DestinationVolumeUUID $mountedDisk
        echo "done."
    fi
else
    echo "No Backup HD found."
fi

Make sure to change the reference to “Backup HD” (on the second line) to the name of your backup drive(s) if it differs.

Save this file with an appropriate name to an appropriate location. I named it rotateDisk and installed it in /usr/local/bin, which is a more UNIX approach. Feel free to put it in /Applications/Utilities or any other preferred location. Note the full path to it as you will need to change its permissions as follows:

chmod 755 /usr/local/bin/rotateDisk

So, how does this script work:

  1. First, it uses diskutil to get the UUID of any hard drive connected with the name “Backup HD”. If no such drive is connected, the script exits.
  2. Second, it checks Time Machine’s preferences to see which UUID it’s currently configured to backup to.
  3. If they don’t match, it updates Time Machine’s preferences to reflect the connected drive’s UUID.

Since Time Machine checks its preferences at each hourly backup, there’s no need to restart any process to observe the changed preferences.

Using launchd, part of OS X since Tiger, we can configure the above script to run any time a volume is mounted. Perfect!

With our trusty text editor, let’s create a launchd job description:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.thepracticeofcode.TimeMachine.rotate</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/rotateDisk</string>
    </array>
    <key>RunAtLoad</key>
    <false/>
    <key>StartOnMount</key>
    <true/>
</dict>
</plist>

Make sure to change the path to the script appropriately. You are welcome to use spaces in that declaration if necessary.

This file needs to be stored in /Library/LaunchDaemons/ and it needs to be owned by root and have the following permissions:

-rw-r--r--  1 root  wheel  431 Jun 29 13:55 /Library/LaunchDaemons/com.thepracticeofcode.TimeMachine.rotate.plist

To facilitate that, after you have moved/copied it there, run (as root or with sudo):

chown root:wheel /Library/LaunchDaemons/com.thepracticeofcode.TimeMachine.rotate.plist
chmod 644 /Library/LaunchDaemons/com.thepracticeofcode.TimeMachine.rotate.plist

You can load the job manually or it will automatically load at restart. To load manually, type (again, as root or with sudo):

launchctl load /Library/LaunchDaemons/com.thepracticeofcode.TimeMachine.rotate.plist

To test, open Console and watch system.log and eject and re-connect one of your backup disks. If everything is going well, you should see the following output:

Jun 29 22:43:27 server com.thepracticeofcode.TimeMachine.rotate[29635]: Mounted Disk UUID: 58513F29-10AD-3445-B251-9F0E51841A2C
Jun 29 22:43:27 server com.thepracticeofcode.TimeMachine.rotate[29635]: Configured Disk UUID: 58513F29-10AD-3445-B251-9F0E51841A2C
Jun 29 22:43:27 server com.thepracticeofcode.TimeMachine.rotate[29635]: Configuration is correct.

If the drive is different to the last drive configured, the output will be slightly different, like this:

Jun 29 13:55:41 server com.thepracticeofcode.TimeMachine.rotate[88102]: Mounted Disk UUID: 58513F29-10AD-3445-B251-9F0E51841A2C
Jun 29 13:55:41 server com.thepracticeofcode.TimeMachine.rotate[88102]: Configured Disk UUID: 996F3C3D-F83C-3FD4-84B5-B5AE1F5CB03D
Jun 29 13:55:41 server com.thepracticeofcode.TimeMachine.rotate[88102]: Configuration requires update. Updating...
Jun 29 13:55:41 server com.thepracticeofcode.TimeMachine.rotate[88102]: done.

Retrieving Backups Using Time Machine.app

Initially, I had never investigated using the Time Machine app to retrieve files. I had always used Terminal. A few commenters pointed out that using the Time Machine app to restore contents failed as it showed there were no backups present. However, commenter Dev Null pointed to a similar article by Chuck Burt which offers the following trick:

"Note, that due to a bug in Time Machine, you will no longer be able to go to “Enter Time Machine” to browse your backups using the slick Time Machine UI. If you want to get around this, mount the sparse bundle. Once it is mounted, go to the Time Machine menu item and hold the option key. This will make an option appear called “Browse Other Time Machine Disks.” Click it (while holding option). A menu will pop up that allows you to enter the Time Machine interface."

Performing a Full Restore using OS X DVD

Similar to to the last paragraph, this is not a feature I’ve ever used. However, much thanks to Brett Gallagher for writing in with a solution to this one:

If you’re wanting to restore from a Time Machine backup using the OS X Install DVD, it’s not possible to automatically do so - the drive you’re using the backup with will show up, but once you select it it won’t show any backups as being available to select from. In order to get around this, you need to open Terminal, and type hdiutil attach /Volumes/BackupDrive/ComputerName.sparsebundle, and enter the password for the .sparsebundle. Once you have done this, going back into “Restore from Time Machine backup” should present the disc image as an option, and the list of backups should be able to be selected from there.

That’s it!

  • Thanks to Curmi for showing me how to do this in Leopard.
  • Thanks to sunkid for showing me how to properly create a Time Machine backup image
  • Thanks to Mac OS X Hints for publishing sunkid’s hint.
  • Thanks to Alf and Dev Null for rounding out the edges with some updates.

Please let me know if you find any inconsistencies or mistakes in the above or if something just isn’t working as expected.

Wednesday, June 30, 2010 — 17 notes   ()