Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Paraphraser/c7a37cd8f89ee448148399b519b0cb88 to your computer and use it in GitHub Desktop.
Save Paraphraser/c7a37cd8f89ee448148399b519b0cb88 to your computer and use it in GitHub Desktop.
Using SSHFS to mount your Raspberry Pi's home directory on your Mac

Using SSHFS to mount your Raspberry Pi's home directory on your Mac

It is useful to be able to mount your Raspberry Pi's file system on your Mac's desktop. The Raspberry Pi is ready to rock-'n-roll but some work needs to be done on the Mac. This gist assumes macOS Mojave 10.14. Your mileage may vary on earlier or later versions.

Set up passwordless SSH (optional)

You can make your life quite a bit simpler if you set up SSH on your Mac so that it can login to your Raspberry Pi without needing a password. Follow this tutorial.

The tutorial assumes two Raspberry Pis but there is no difference in approach if you use a Mac and a Pi, or two Macs.

Install HomeBrew (one-time)

If you don't have HomeBrew installed on your Mac, follow the installation instructions.

Install SSFS (one-time)

Current instructions (as at July 2021)

To install the Secure-Shell File System support (SSHFS):

  1. If you have worked through these instructions before but are now getting errors from Homebrew like this:

    Error: sshfs has been disabled because it requires closed-source macFUSE!

    the first thing you need to do is to un-install the old version of sshfs:

    $ brew update
    $ brew uninstall sshfs
    
  2. Either:

    or, if MacFUSE is already installed:

    • Open "System Preferences"
    • Click "MacFUSE"
    • Click "Check for updates" and follow your nose.
  3. Install SSHFS:

    $ brew install gromgit/fuse/sshfs-mac
    

    See also gromgit/homebrew-fuse.

Original instructions (obsolete)

To install the Secure-Shell File System support (SSHFS), do:

$ brew update
$ brew install sshfs

Define a mount point for your Raspberry Pi

A mount-point is just a folder. It can be anywhere on your Mac. Your home directory is just as good as anywhere else.

For example, if you have given your Raspberry Pi the name "mypi" then you could create the mount-point folder like this:

$ mkdir ~/mypi

This folder is only "special" when it is being used as a mount point. Otherwise, it is just an ordinary folder.

Mount your Raspberry Pi's home folder

The syntax is:

sshfs «user»@«host»: «mountPoint»

where:

  • «user» is the username on the Raspberry Pi (eg "pi"). This field and the trailing @ can be omitted if you set up an ssh config.

  • «host» is an identifier for the Raspberry Pi. It could be:

    • an IP address - eg "192.168.203.10"

    • a multicast DNS name - eg "mypi.local"

    • a fully-qualified domain name - eg "mypi.mydomain.com"

    • the ssh host identifier - eg "mypi" - providing you have set up an ssh config. A typical entry would be:

       host mypi
         # enable whichever form of "hostname" is most appropriate
         hostname 192.168.203.10
       # hostname mypi.local 
       # hostname mypi.mydomain.com 
         user pi
         UseKeychain yes
      
  • «mountPoint» is the path to the mount point created in the previous step

Note the trailing colon and space separating the «host» from the «mountPoint». Don't omit either of those characters!

Examples:

$ sshfs pi@192.168.203.10: ~/mypi
$ sshfs pi@mypi.local: ~/mypi
$ sshfs pi@mypi.mydomain.com: ~/mypi
$ sshfs mypi: ~/mypi

Always be very careful to get the "«user»@«host»" exactly right. Any mistake can hang this command, hang the Finder (spinning beachball) and result in the need for a forced power-off/power-on. If you happen to have another Terminal window open, you can get away with a "killall sshfs" but that still leaves the mount point in an indeterminate state and a restart is the only way to recover. Not very Mac-like, I know.

The first time you run sshfs, your action will almost certainly be blocked by that ever-present pestilence masquerading as a benevolent computer nanny: GateKeeper. You will need to navigate to the "Security & Privacy" panel of "System Preferences", authenticate, and permit the action.

Working with the remote volume

The remote volume will mount on your desktop. You can copy files into and out of the Raspberry Pi's volume. You can also access the remote volume from the macOS Terminal like this:

$ cd ~/mypi

Un-mounting the remote volume

When you are finished, drag the volume to the trash to eject it. Alternatively, you can un-mount it from macOS Terminal like this:

$ umount ~/mypi

Saving yourself some time

You can save yourself some time and avoid having to remember the sshfs command syntax by creating a "mount script" for each of your Raspberry Pis:

  1. Copy the content below into a text editor:

    #!/usr/bin/env sh
    
    RASPBERRYPI="mypi"
    MOUNTPOINT="$HOME/$RASPBERRYPI"
    
    # ensure mount point exists (non-destructive)
    mkdir -p "$MOUNTPOINT"
    
    # mount the volume
    sshfs "$RASPBERRYPI": "$MOUNTPOINT" -ovolname="$RASPBERRYPI"
    
    # reminder
    echo "Unmount $RASPBERRYPI by dragging to trash or type 'umount $MOUNTPOINT'"
    
  2. Edit the "RASPBERRYPI" variable so that it equals the name of your Raspberry Pi.

  3. Save the file in your search path (eg ~/.local/bin) with a name like "mount_mypi".

Once you have done that, you can mount your Raspberry Pi's home folder by typing:

$ mount_mypi

Notes:

  1. Don't worry about the mkdir -p command. It is completely non-destructive:

    • If the folder already exists, mkdir -p does absolutely nothing.
    • If the folder already exists and contains files and folders when this script is run, those become inaccessible while the folder is being used as a mount-point. As soon as you dismount the remote volume, the folder goes back to being a regular folder with its contents are intact.
  2. The script structure assumes that the "RASPBERRYPI" variable equals a host identifier defined in your ssh config. You will need to adjust the sshfs command if you have not set up an ssh config.

a word about Resource Forks

Resource Forks hail from the original "classic" Mac of the 1980s and were inherited by Mac OS X (since renamed macOS). The easiest way to understand what a Resource Fork represents is to visualise how any computer file system must work. At its simplest, a directory is just a table where each row contains a file name and a pointer to the start of the file's data on the disk:

FileName Data
fred.txt 5
freddy.txt 7

In words: the data for the file fred.txt starts at sector 5; and the data for the file freddy.txt starts at sector 7.

In a macOS file system, each row in the directory has two pointers, one to the Data Fork and the other to the Resource Fork:

FileName Data Resource
fred.txt 5
freddy.txt 7 15

In words: the Data Fork for the file fred.txt starts at sector 5 but it does not have a Resource Fork; the Data Fork for the file freddy.txt starts at sector 7, and its Resource Fork starts at sector 15.

The Data Fork meets the standard definition of a computer file on any operating system: an unstructured sequence of bytes where any structure is imposed by the application(s) that read or write the file. The structure of the Resource Fork has always been defined by macOS and can be thought of as a kind of key-value store.

The purpose of the Resource Fork changed when Mac OS X came along and is now mostly used to store extended attributes. Not every file has extended attributes so, most of the time, there will be no Resource Fork. But, when a non-Mac file system (eg your RPi ext4 partition) is mounted on a Mac and something happens on the Mac side which causes the file to acquire a resource fork, a hidden shadow file will turn up to hold the data associated with the resource fork.

The shadow files all begin with ._ (dot underscore). For example (from macOS Terminal):

$ ls -lno .DS_Store freddy.txt ._*
-rw-r--r--@ 1 501  8196 Aug 15 18:32 .DS_Store
-rw-r--r--  1 501  4096 Aug 15 14:18 ._.DS_Store
-rw-r--r--  1 501  4096 Aug 16 10:08 ._freddy.txt
-rw-r--r--@ 1 501     9 Aug 16 10:08 freddy.txt

.DS_Store and freddy.txt are Data Forks while ._.DS_Store and ._freddy.txt are Resource Forks. The "@" at the end of the file flags for the two Data Forks means "extended attributes are defined" so that's also a clue to the presence of a Resource Fork. We can ask macOS to tell us what those extended attributes are (from macOS Terminal):

$ ls -@lno .DS_Store freddy.txt
-rw-r--r--@ 1 501  8196 Aug 15 18:32 .DS_Store
	com.apple.FinderInfo	  32 
-rw-r--r--@ 1 501     9 Aug 16 10:08 freddy.txt
	com.apple.metadata:_kMDItemUserTags	  42 

If you run the same commands from the Raspberry Pi OS command line:

$ ls -lno .DS_Store freddy.txt ._*
-rw-r--r-- 1 1000 4096 Aug 15 14:18 ._.DS_Store
-rw-r--r-- 1 1000 8196 Aug 15 18:32 .DS_Store
-rw-r--r-- 1 1000 4096 Aug 16 10:08 ._freddy.txt
-rw-r--r-- 1 1000    9 Aug 16 10:08 freddy.txt

$ ls -@lno .DS_Store freddy.txt
ls: invalid option -- '@'
Try 'ls --help' for more information.

In short, Raspberry Pi OS can see the hidden shadow files but has no idea what they mean.

Most of the time the hidden shadow files don't cause any problems but you may find them showing up in unexpected places such as git status if you have not told git to ignore them.

It causes no harm whatsoever to simply remove the hidden shadow files. I define this alias in my Raspberry Pi OS profile for the purpose:

alias KILLRESOURCEFORKS='sudo find . -name "._*" -delete'

Whenever I spot an unwanted resource fork, I type "K" and hit tab which auto-completes to KILLRESOURCEFORKS, and then I hit ⏎. All gone!

and, while we're on the topic of hidden macOS files…

A similar comment applies to .DS_Store files. These are (roughly) equivalent to Thumbs.db on Windows. I define another alias to get rid of those when I see them:

alias DSSTORES='sudo find . -type f \( -name ".DS_Store" -o -name "._.DS_Store" \) -delete'

Rest assured, removing these files is harmless to both Raspberry Pi OS and macOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment