MacOS Time Machine to SMBFS
In late-Jan/early-Feb of 2023, I set up my wife’s aged iMac (mid-2010) to back itself up, via Time Machine, to a Samba file share on a server in my home, in addition to the Firewire 800 removable drive that it has used for years. I learned a lot in the process that I don’t want to forget, and so I decided to write a blog post so that it may also help others.
Introduction
Time Machine is a nice and quite reliable tool for backing up MacOS. Shortfalls of having it backup to only a local drive are things like the danger of concurrent failure (like lightning damage) or theft. And so, having Time Machine backup to a network file server is an attractive option, particularly if you have Time Machine target both a local and a network disk, which is supported.
The way that my wife’s iMac is setup now is that it backs itself up to two places:
- A local Firewire 800 portable drive.
- A SMB file share on a Linux machine served via Samba.
The article How to Configure Time Machine to Backup to Samba Shared Folder is a nice and quick run through of how to setup Time Machine backups to a samba share. I followed it, but then was unhappy with the final result and kept working to a solution that I much prefer. The primary purpose of this blog post is to document what I did past where that article leaves things.
Time Machine and Network Shares
In order for Time Machine to backup to network shares, you must create a “sparse bundle” file (disk image) for it to use, which is shown in the article cited above. And so, in short, you first must “mount” two things, in this order, to perform backups:
- The samba file share.
- The “sparse bundle” disk image (a *.dmg file).
What I did beyond the article cited above was to fully automate the mounting of both of those items with no regard to if, and if so who, logs into the Mac. If only a single user uses the Mac, and does so often, then what I did may not be necessary, but that was not my situation, plus I prefer this process that does not rely on any user ever logging in.
My Setup
I settled on a setup where automount is used on MacOS to automatically mount the samba file share and a cron job is used to insure that the *.dmg file for Time Machine is mounted. Really, the cron job leads everything because the automount won’t even happen until/unless an access is attempted on the automounting SMB file share, and my cron job does that.
Automount Config
I have used automount for many years, and I like to configure my autofs mount points into /vol. And so, I added this line to my /etc/auto_master file:
/vol auto.vol
And this line to my new /etc/auto.vol file:
zion_time_machine -fstype=smbfs,soft,noowners,nosuid,noatime,rw ://uname:pword@zion.localdomain/macos_time_machine
After running automount -vc, attempts to access /vol/zion_time_machine will immediately cause the mounting of that network drive.
NOTE: you will have a plain text uname/pword combo stored within the file /etc/auto.vol and so be sure that root owns it and that the permissions are set to 0600 (readable only by root).
Using hdiutil to Mount the Time Machine dmg
Now that /vol/zion_time_machine/ automounts, the Time Machine dmg file that lives on it can be mounted (attached). I chose to write a script to do that and use cron to routinely exectute it. I will review the reasons for that in the Notes/Caveats section below, but for now, here is that script:
#################################################################
# This script is used to mount (ensure the mount of) the file
# TimeMachine-imac-mid-2010.sparsebundle.dmg that is hosted on
# zion, to which Time Machine makes backups. It can be run by a
# user or run from cron. Initially, I set this up to only run at
# user logins, but that was not reliable enough and so I made a
# cron job for it.
#
# It checks for the UUID of the partition that we care about that
# is inside of TimeMachine-imac-mid-2010.sparsebundle.dmg
# (via "hdiutil info") and mounts it if it's not already mounted.
#################################################################
#imac:bin hightowe$ hdiutil info
#framework : 480.60.1
#driver : 10.13v480.60.1
#================================================
#image-path : /vol/zion_time_machine/TimeMachine-imac-mid-2010.sparsebundle.dmg
#image-alias :
#shadow-path : <none>
#icon-path : /System/Library/PrivateFrameworks/DiskImages.framework/Resources/CDiskImage.icns
#image-type : read/write
#system-image : false
#blockcount : 976562540
#blocksize : 512
#writeable : TRUE
#autodiskmount : TRUE
#removable : TRUE
#image-encrypted : false
#mounting user : ellen
#mounting mode : <unknown>
#process ID : 2560
#/dev/disk3 GUID_partition_scheme
#/dev/disk3s1 C12A7328-F81F-11D2-BA4B-00A0C93EC93B
#/dev/disk3s2 48465300-0000-11AA-AA11-00306543ECAC /Volumes/TimeMachine to Zion
DMG_FILE="/vol/zion_time_machine/TimeMachine-imac-mid-2010.sparsebundle.dmg"
PART_UUID="48465300-0000-11AA-AA11-00306543ECAC"
EXP_MNTPNT="/Volumes/TimeMachine to Zion"
# Mount it if needed
MNT_COUNT=$( hdiutil info 2>&1 | /usr/bin/egrep -c "$PART_UUID" )
if [ "$MNT_COUNT" -gt 1 ]; then
echo "`date`: $DMG_FILE is mounted $MNT_COUNT times!!!"
exit
elif [ "$MNT_COUNT" -eq 0 ]; then
if [ ! -f "$DMG_FILE" ]; then
echo "`date`: Need to mount $DMG_FILE but do not see it!"
exit
fi
echo "`date`: Using hdiutil attach to mount $DMG_FILE."
hdiutil attach "$DMG_FILE"
fi
# Did it work?
new_mnt_cnt=$( hdiutil info 2>&1 | /usr/bin/egrep -c "$PART_UUID" )
if [ "$new_mnt_cnt" -ne 1 ]; then
echo "`date`: FAILURE - $DMG_FILE is mounted $new_mnt_cnt times!!!"
elif [ "$new_mnt_cnt" -ne "$MNT_COUNT" ]; then
# Note that the hdiutil output is tab separated
#MNT_POINT=$( hdiutil info | grep "$PART_UUID" | sed -E "s/^.+$PART_UUID[ ]+//" )
MNT_POINT=$( hdiutil info | grep "$PART_UUID" | cut -d' ' -f3 )
echo "`date`: $DMG_FILE is now mounted on $MNT_POINT"
if [ "$MNT_POINT" != "$EXP_MNTPNT" ]; then
echo "WARNING: mounted at $MNT_POINT instead of where expected: $EXP_MNTPNT"
fi
fi
And then this cron job is installed to run that script periodically:
imac:~ hightowe$ crontab -l
MAILTO=my.redacted@email.address
#0,10,20,30,40,50 * * * * /Users/hightowe/bin/mount_zion_time_machine.sh 2>&1 1>>/Users/hightowe/bin/mount_zion_time_machine.sh.log
0,10,20,30,40,50 * * * * /Users/hightowe/bin/mount_zion_time_machine.sh 2>&1 | /usr/bin/tee -a /Users/hightowe/bin/mount_zion_time_machine.sh.log
The job with the “tee” is emailing me when the script actually takes an action, and I intend to keep it that way for a few days/weeks until I am convinced that this process is solid, and then I’ll stop those emails.
Notes/Caveats
Mountpoint Permissions with Automount
At least as I have it configured, and I could not find a way to solve this, automount mounts the SMB file share as the user who first accesses the share and only that user (and root) can then see the share. All other users receive permission denied. When I was using user login actions to run the hdiutil attaching, it would fail if user A had mounted the SMB file share and user B logged in and tried to do the hdiutil attaching. After unsuccessfully fiddling with that for quite a while, I decided to move to the method described herein as it does not rely on user logins.
I chose to not run any of this as the root user (personal quirk), but I see no reason that that would not work, but I also see no downside to running it as my user on the machine and so that it my preference.
Operating System Version
This work was done on High Sierra (10.13.6), with all of the most recent updates installed, but keep in mind that it is now well over two years past end-of-life. There is a chance that this process will not work the same on newer version of macOS, and it may be a while before I get a chance to test that.