Auto-mount NAS shares on a Mac and keep them mounted
A launchd job and a bash script that mount SMB shares at login, remount after sleep or network changes, and clear stale mounts. Download included.
macOS can reopen a share at login (add it under System Settings → General → Login Items), but it gives up if the NAS isn’t reachable at that moment. It also doesn’t notice when a mount goes “stale” after sleep or a Wi-Fi change: Finder shows the drive, but anything that touches it hangs.
This setup fixes both. It’s a real script that has been running on an Oddbyte.Me home lab Mac. Personal details have been swapped for placeholders.
Downloads: nas-mount.sh · nas-mount.conf.example · com.example.nas-mount.plist
How it works
A launchd agent runs the script at login, every 60 seconds, and whenever /var/run/resolv.conf changes. That file is rewritten when the Mac joins a network, so it’s a cheap “network changed” trigger. Each run of the script does this:
- Lock check: it skips the run if another copy is already running. A lock older than 10 minutes counts as leftover and is cleared.
- Wait for a network: for up to 60 seconds it checks every 2 seconds for a default route, so it doesn’t try to mount before Wi-Fi is up. If there is still no route, it logs that and exits until the next run.
- Check each share:
- Already mounted? It tests the mount with a time limit (
lsin the background, killed after about 6 seconds). If the test hangs, the mount is stale, so it force-unmounts (umount -f) and remounts. - NAS reachable? It probes TCP port 445 (SMB) with
nc, retrying every few seconds for roughly 45 seconds (a little longer if each probe times out), so an unreachable NAS produces one clean log line instead of a Finder error. - Mount it with AppleScript’s
mount volume. This mounts the share under/Volumes/<share>just as Finder would, so it shows up in the sidebar.
- Already mounted? It tests the mount with a time limit (
- Log: mounts, failures, stale mounts and unreachable hosts are written to
~/Library/Logs/nas-mount.log. A run where everything is already mounted and healthy writes nothing.
Install
-
Save the script, for example to
~/Scripts/nas-mount.sh, and make it executable:mkdir -p ~/Scripts && mv ~/Downloads/nas-mount.sh ~/Scripts/ chmod +x ~/Scripts/nas-mount.sh -
Create the config and lock it down. It holds passwords, so only your account should be able to read it:
cp ~/Downloads/nas-mount.conf.example ~/.nas-mount.conf chmod 600 ~/.nas-mount.conf open -e ~/.nas-mount.confEach share is one line:
"HOST|SHARE"(this uses the default login) or"HOST|SHARE|USER|PASSWORD". A host name without a dot, likemynas, gets.localadded for the reachability probe; the mount itself uses the name exactly as written. -
Edit the plist so the second
ProgramArgumentsentry is your script’s full path. Then load it as a per-user agent:cp ~/Downloads/com.example.nas-mount.plist ~/Library/LaunchAgents/ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.nas-mount.plist -
Watch it work:
tail -f ~/Library/Logs/nas-mount.log
To stop it, run launchctl bootout gui/$(id -u)/com.example.nas-mount.
Per-user vs system-wide. Apple’s launchd guide says agent property lists go in
/Library/LaunchAgentsor theLaunchAgentsfolder in a user’s ownLibrary(~/Library/LaunchAgents), and daemon property lists go in/Library/LaunchDaemons. It describes a user agent as specific to one logged-in user, running only while that user is logged in. Mounting through Finder needs your login session, so use a per-user agent, not a daemon.
Adapting it
| You want to… | Change |
|---|---|
| Check more or less often | StartInterval in the plist (seconds) |
| Wait longer for slow-booting NAS units | HOSTWAIT and NETWAIT at the top of the script |
| Use NFS or AFP instead of SMB | Change the port in the nc probe (NFS 2049, AFP 548) and the smb:// URL |
| Mount somewhere other than /Volumes | Replace the AppleScript line with mount_smbfs to a folder you own (Finder won’t show it in the sidebar the same way) |
| Avoid storing passwords in a file | Save the password in Keychain, then read it in the script with security find-internet-password -s HOST -a USER -w |
Notes and gotchas
- Passwords: the AppleScript is fed through a heredoc on standard input, so the password never appears on the command line where other processes could see it. It is still stored in plain text in
~/.nas-mount.conf, which is why that file getschmod 600. - Stale mounts: the output of
umount -fgoes into the log too. In our use, an error from it right before a successful remount was harmless: the force-unmount can fail on a dead mount while the remount still works. - Old notes: many of the older AppleScript-only automount guides you’ll find online don’t handle stale mounts or wait for the network, and those are exactly the failures this script was written for.
Sources
- Creating Launch Daemons and Agents — by Apple Developer Documentation (archive)