Janw.xyz

Jack of all trades and a master of some

Move your iOS device backups out of iCloud to your Mac

So you might have heard about how the FBI is currently trying to push Apple to decrypt information on an iOS device owned by one of the San Bernadino terrorists. I’m not well at explaining such events, but there are lots of reports on the case, and Gernot Poetsch wrote about the technical side of things.

At the end of Gernot’s article there is a suggestion that privacy advocates have been screaming from the roofs ever since Apple drastically simplified iOS device backups by moving them to iCloud: Don’t use it. Any iOS device backups in iCloud are subject to any subpoenas or court orders that Apple might receive. And since they are not as encrypted as they are when done locally, they are practically like an open book to anyone holding a (really really big) grudge against you.

Good news though: iTunes is still here and while being in generally bad shape it also still supports local backups for iOS devices. If you configured that instead of iCloud backups: good! Make sure not to miss the “encrypt local backups” checkmark as well. If you haven’t configured, that’s probably because triggering a new backup always requires you to manually open iTunes, click through to the device info, and hit the “Backup now” button. Let’s change that and move the stuff back to where it belongs: your own local data storage. All it takes is a Mac, and a little bit of scripting magic.

One of the most underrated capabilities of OS X is the rather good integration of Apple’s own basic scripting language, called Apple Script. With that you can trigger repetitive tasks, simplify workflows and handle applications as if you where clicking through their GUIs, but from the sweet home of your shell. iTunes is one of the applications having great coverage of Apple Script commands, and as you might have guessed, even backing up an iOS device can be done by a script. From that moment on it’s just a matter of selecting a time for the script to run, and you are basically done (almost) replicating the iCloud device backup experience.

The idea of introducing automation to iTunes syncing is pretty old already. Doug’s AppleScript Site contains postings from 2011 and 2012 about how to sync your iPods/iPads/iPhones daily using Apple Script, and the scripts used down below are only slightly modified versions of his. So Kudos to him, but this deserves reiteration.

Creating the Apple Script

The first thing you need is the script for handling iTunes. Compared to Doug’s version I basically added parts where iTunes would be launched when not already open, and a message to the system’s log. So we’ll create /Users/janwillhaus/Library/iTunes/Scripts/Backup All Devices.scpt. Or you know, rather the same for your username. It will contain the following:

do shell script "syslog -s -l notice Start syncing devices in iTunes"

if not checkItunesIsActive() then
    tell application "iTunes" to activate
    tell application "Finder" to set visible of process "iTunes" to false
end if

tell application "iTunes"
    try
        set theSources to (every source whose kind is iPod)
        repeat with src in theSources
            try
                with timeout of 600 seconds
                    if (get name of src) is in {"Jans iPhone", "Jans iPad"} then
                        tell src to update
                    end if
                end timeout
            end try
        end repeat
    end try
end tell

to checkItunesIsActive()
    tell application id "sevs" to return (exists (some process whose name is "iTunes"))
end checkItunesIsActive

Make sure to add your devices where I entered "Jans iPhone", "Jans iPad". They have to match their name as it shows inside of iTunes. If you just want to backup all of your devices, remove the if-clause in

if (get name of src) is in {"Jans iPhone", "Jans iPad"} then
    tell src to update
end if

to make it

tell src to update

The next time you open iTunes you’ll notice a new icon in the menu bar: The little script icon! Clicking it will reveal all available scripts from your iTunes Scripts directory, and: “Backup All Devices”. From this point on, you can initiate a backup of all devices from a single click. Just make sure to initiate a backup manually once via the “Back Up Now” button in the Device Summary view. It might be necessary to properly set-up the encryption passphrase etc. Moving on to automation!

Running the Script using Launchd

This is where Launchd comes into play. Launchd is OSX’s framework for starting, running, supervising, and stopping services. We’ll use a Launchd agent to automate the execution of our previously created backup script. Each service is based on a launch agent script, which in turn based on a plist file (technically an XML file). That script tells Launchd when to launch the service, and (if needed) a ton more. Our agent com.janwillhaus.iTunesDeviceBackups.plist is fairly simple: it will execute the backup script and be done. The launch agent file will be placed in /Library/LaunchAgents/, the place for system-wide services. It contains this:

<?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>Disabled</key>
        <false/>
        <key>UserName</key>
        <string>janwillhaus</string>
        <key>Label</key>
        <string>com.janwillhaus.iTunesDeviceBackups</string>
        <key>Program</key>
        <string>/usr/bin/osascript</string>
        <key>ProgramArguments</key>
        <array>
                <string>osascript</string>
                <string>/Users/janwillhaus/Library/iTunes/Scripts/Backup All Devices.scpt</string>
        </array>
        <key>StartCalendarInterval</key>
        <dict>
                <key>Hour</key>
                <integer>3</integer>
                <key>Minute</key>
                <integer>0</integer>
        </dict>
</dict>
</plist>

This tells Launchd to run the applications osascript with the backup script as an argument. As noted by <key>UserName</key> <string>janwillhaus</string>, Launchd is actually executing this as if it was run by me. Make sure to replace janwillhaus with your own username (at two places), though. The <dict> underneath StartCalendarInterval tells Launchd when to execute the script. So when your are running iTunes on a home server like I do, it should be fine, to run it at a time when network traffic, and device usage probability is relatively low, for example 3:00 in the morning.

No for activating this, you could just wait for the next reboot of your machine, or initiate loading the launch agent by executing

launchctl load /Library/LaunchAgents/com.janwillhaus.iTunesDeviceBackups.plist

at the Terminal: If you modified the launch agent plist and want to reload it simply enter

launchctl unload /Library/LaunchAgents/com.janwillhaus.iTunesDeviceBackups.plist
launchctl load /Library/LaunchAgents/com.janwillhaus.iTunesDeviceBackups.plist

“So you plugged this in and you’re done!” If you want to see afterwards if backups have been created, check in iTunes in the iOS device info page, there is a “Last backup” reading. Also in Console.app, there will be a line logged stating Start syncing devices in iTunes that the backup script created. So there you go. Not that complicated, right? Of course it is not 100% equivalent to the ease-of-use of iCloud backups and it requires you to actually want to use it, since you have to have a Mac running iTunes, only have it working in your home WiFi etc. But if you do care about your privacy, and—in a way—your informational independence, this is the way to go.