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:
- Mount the share. If you run the “mount” command in a Terminal window or open Disk Utility you will see it mounted.
- 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.
- Unmount the network share and mount the sparse bundle directly.
- Write all the backup data to the mounted sparse bundle.
- 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:
- Mount the network file share with a “hard mount” so that brief network interruptions won’t cause Time Machine to freak out.
- Create a sparse bundle manually on the mounted network file share rather than letting Time Machine do it.
- Mount the sparse bundle.
- Tell Time Machine to use the sparse bundle as its backup location.
- 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
- Open Disk Utility.
- Select File | New Image | Blank Image…
- Open the folder
~/Mountpoints/TimeMachineBackups
or wherever you mounted the network file share. - Enter the name you want to save the bundle as in the “Save as” and “Name” fields.
- Change the “Image Format” field to “sparse bundle disk image”.
- Change the “Size” field to the size of your hard disk.
- 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:
- Creating a sparse bundle, and telling Time Machine to use it using
tmutil setdestination
: https://kb.lsa.umich.edu/public/index.php/Backing_up_with_Time_Machine_to_network_storage_using_a_sparse_bundle - Running a script on login: https://stackoverflow.com/questions/6442364/running-script-upon-login-mac/13372744#13372744
- Mounting a sparse bundle from the command line: https://apple.stackexchange.com/a/23523
- Preventing a mounted filesystem from showing up on the Desktop: https://www.idownloadblog.com/2016/12/02/how-to-hide-mounted-volumes-from-desktop-finder/
Don’t use AFP. Turn it all off and use SMB only.
I tried SMB; it had the same problem.