How I got Time Machine backups to work with my Synology NAS

By | August 13, 2020

I just got a MacBook Pro running macOS Catalina for work, and I wanted to set up Time Machine backups for it to the Synology NAS in my basement so that if the laptop dies or is lost and I need to replace it, I won’t have to redo all of the customizations it took me hours to set up. (I’m separately backing up my data files using Backblaze, but Backblaze doesn’t back up system files and applications.)

I followed Synology’s instructions for using my NAS as a Time Machine backup target, but I couldn’t get the first, full backup to complete successfully after doing that. When Time Machine started to back up, it would say “Looking for backup disk” and then say “Preparing backup” and then stop one or two minutes later with no error message. Below, I explain what I investigating this problem, and how I ultimately solved it.

This article is probably applicable to other Macs (not just MacBook Pro) and other NAS servers (not just Synology).

How backing up to a network drive works

All of these steps need to complete for the first, full Time Machine backup to a network share to succeed:

  1. Mount the share. If you run the “mount” command in a Terminal window or open Disk Utility you will see it mounted.
  2. Create a “sparse bundle” on the network share to hold the backup. Basically, this is a disk image stored on the network share that can be mounted as a separate filesystem. Initially the sparse bundle is created with a random name (I think), but after it’s successfully created it’s renamed to contain the host name of the computer being backed up.
  3. Unmount the network share and mount the sparse bundle directly.
  4. Write all the backup data to the mounted sparse bundle.
  5. Unmount the sparse bundle.

What was going wrong

TL;DR It’s the WiFi, dammit.

I kept running the backup. It kept failing part of the way through step 2, i.e., creating the sparse bundle. I know this because I was watching the file share in which the sparse bundle is stored, and each time the backup ran it deleted and recreated the sparse bundle from scratch, and each time it exited prematurely the sparse bundle was a different size.

Eventually Time Machine did manage to successfully create and rename the sparse bundle, but then after that it once again stopped prematurely a couple of minutes into writing the backup data. Each time I restarted the backup it would write a little more data and then stop prematurely.

To diagnose this further, I ran a ping command in a Terminal window while the backup was running, pinging the NAS. Here’s what I saw immediately before the backup failed:

64 bytes from 192.168.4.16: icmp_seq=48 ttl=64 time=1.905 ms
64 bytes from 192.168.4.16: icmp_seq=49 ttl=64 time=2.760 ms
ping: sendto: No route to host
Request timeout for icmp_seq 50
ping: sendto: No route to host
Request timeout for icmp_seq 51
ping: sendto: No route to host
Request timeout for icmp_seq 52
Request timeout for icmp_seq 53
64 bytes from 192.168.4.16: icmp_seq=54 ttl=64 time=5.702 ms
64 bytes from 192.168.4.16: icmp_seq=55 ttl=64 time=3.612 ms

One of two things was happening: either the NAS was briefly becoming inaccessible to my Mac in the middle of the backup, or my Mac was briefly losing network connectivity in the middle of the backup. To determine which of these was the case, I ran the backup again, but this time rather than pinging the NAS during the backup, I pinged another machine on the network. I saw the same brief interruption, which proved that it was the Mac, not the NAS, that’s losing network connectivity briefly during the backup.

This is not surprising, since if you spend some time Googling, you will discover that there are a lot of complaints online about Macs intermittently dropping their WiFi connections briefly. No one really has a good explanation for why this happens or how to fix it. It appears that this is just a widespread problem in Mac WiFi support that Apple hasn’t prioritized fixing.

Unfortunately, the AFP over TCP network filesystem protocol code in the Mac kernel is apparently extremely sensitive to brief interruptions in network connectivity and incapable of recovering from brief network connections. Therefore, every time this WiFi blip happens, Time Machine gets back a filesystem error from the kernel and aborts the backup.

How I fixed it

At a high level, here’s what I did to fix this:

  1. Mount the network file share with a “hard mount” so that brief network interruptions won’t cause Time Machine to freak out.
  2. Create a sparse bundle manually on the mounted network file share rather than letting Time Machine do it.
  3. Mount the sparse bundle.
  4. Tell Time Machine to use the sparse bundle as its backup location.
  5. Set up a launch agent task to mount the network file share and sparse bundle automatically every time I log in.

Hard-mounting the network file share

mkdir -p ~/Mountpoints/TimeMachineBackups
mount_afp -k afp://username:password@hostname.local/sharename ~/Mountpoints/TimeMachineBackups

The key here is the -k argument to mount_afp, which is what specifies a hard mount.

Creating the sparse bundle

  1. Open Disk Utility.
  2. Select File | New Image | Blank Image…
  3. Open the folder ~/Mountpoints/TimeMachineBackups or wherever you mounted the network file share.
  4. Enter the name you want to save the bundle as in the “Save as” and “Name” fields.
  5. Change the “Image Format” field to “sparse bundle disk image”.
  6. Change the “Size” field to the size of your hard disk.
  7. Click “Save”.

Mount the sparse bundle

Disk Utility will mount the sparse bundle automatically after you create it. Click the eject button in Disk Utility to eject it, and then do something like this:

mkdir -p ~/Mountpoints/TimeMachineBackup
hdiutil attach -mountpoint ~/Mountpoints/TimeMachineBackup ~/Mountpoints/TimeMachineBackups/sparsebundlename.sparsebundle

If the mounted filesystem shows up on your Desktop and you don’t want it there, you can make it disappear like this:

SetFile -a V ~/Mountpoints/TimeMachineBackup
killall Finder

Tell Time Machine where to back up

sudo tmutil setdestination ~/Mountpoints/TimeMachineBackup

You may need to grant Terminal full disk access to run this command. If so, you’ll see an error message in your Terminal telling you that with instructions for how to do it. I recommend turning off full disk access for terminal after it’s done!

Finally, open Time Machine preferences, enable “Back Up Automatically”, enable “SHow Time Machine in menu bar”, click on Time Machine in the menu bar, select “Back Up Now”, and watch the preferences window to make sure everything is working.

Mounting everything automatically using a launch agent

I created this script as ~/scripts/mount_time_machine_backup.sh (I’ve obscured some sensitive details here):

#!/usr/bin/env -S bash -e

unmount=false

while [ -n "$1" ]; do
    case "$1" in
        --mount) unmount=false; shift ;;
        --unmount) unmount=true; shift ;;
        *) echo "Unrecognized argument $1" 1>&2; exit 1 ;;
    esac
done

MP1=~/Mountpoints/TimeMachineBackups
MP2=~/Mountpoints/TimeMachineBackup

if $unmount; then
    hdiutil detach $MP2
    umount $MP1
else
    mkdir -p $MP1
    mount_afp -k afp://username:password@nas.local/Time%20Machine%20Backup $MP1
    mkdir -p $MP2
    hdiutil attach -mountpoint $MP2 $MP1/sparsebundlename.sparsebundle
    # Don't want it to show on Desktop
    SetFile -a V $MP2
    killall Finder
fi

I made the script mode 0700 so I wasn’t exposing my network file share password to the world.

Then I put this in ~/Library/LaunchAgents/comp.jik.TimeMachineMounts.plist:

<?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.jik.TimeMachineMounts</string>
   <key>ProgramArguments</key>
   <array><string>/Users/jik/scripts/mount_time_machine_backup.sh</string></array>
   <key>RunAtLoad</key>
   <true/>
</dict>
</plist>

Then launchctl load ~/Library/LaunchAgents/comp.jik.TimeMachineMounts.plist, and we’re done!

Warnings

My MacBook has crashed at least twice in less than a week since I set this up as described above. Judging from the stack trace that displays after reboot, it looks to me like it’s crashing inside network filesystem code. In addition, each time it has crashed, Time Machine has popped up a message telling me my backup was corrupt and needed to be recreated from scratch. So while the process described above works, it cannot be said to work perfectly, apparently, because of a kernel bug in macOS.

Credits

The following pages written by other people were helpful to me in figuring out much of this, though none of them put all the pieces together quite like I have here:

Print Friendly, PDF & Email
Share

Leave a Reply

Your email address will not be published.