gocryptfs on macOS (with and without macFUSE)
Doing FUSE stuff on a Mac
April 26, 2024
Doing FUSE stuff on a Mac
April 26, 2024
In this post Iām taking gocryptfs as an example because thatās what I use to encrypt my offsite backups, but this can probably be applied to doing anything FUSE-related on a Mac.
Using gocryptfs on macOS requires macFUSE. macFUSE (previously known as OSXFUSE (previously known as MacFUSE lol TIL)) is an awesome project that allows to mount FUSE filesystems on macOS.
All it takes is:
brew --cask install macfuse
# Do the reboot dance to allow the kernel extension (see "concerns" below)
brew install gromgit/fuse/gocryptfs-mac
# Not needed but might as well have SSHFS around too
brew install gromgit/fuse/sshfs-mac
Note: gocryptfs and SSHFS canāt be installed from Homebrewās main registry anymore because they depend on macFUSE, which is not open-source.
This is why the above command installs from this repository, which hosts the Homebrew formulas that depend on FUSE that were dropped from Homebrew.
Sadly, macFUSE is not open-source. But at least itās been updated regularly for over 10 years, and keeps supporting the latest macOS versions, so as long as this stays the case, I donāt mind using it.
That said, depending on macFUSE for a process as critical as my offsite backups means that I will need to wait for it to support a new macOS version before I deem to upgrade. Because itās a kernel extension, itās not necessarily as easy to upgrade as other userland programs.
The other problem is that Apple deprecated kernel extensions in 2020 with macOS Catalina (although they still work up to this date on later versions). This is tracked in this macFUSE issue but at the time of writing, Apple doesnāt provide APIs that allow to implement macFUSE outside of a (now deprecated) kernel extension.
On top of that, going with the deprecation, Apple made it annoying to install kernel extensions on ARM Macs, by having to reboot in recovery and enabling āreduced securityā mode (which is now required for kernel extensions).
While macFUSE works now, and have been working for many years after the original deprecation of kernel extensions by Apple, its future is still somewhat unclear.
In future versions, will macOS drop some the APIs that macFUSE depend on, without providing viable alternatives? Or will they entirely block kernel extensions? And in the event they do provide viable alternative APIs, how long will it take for macFUSE to support that new version?
Otherwise, is any of the alternatives like FUSE-T gonna be solid enough by then? And more importantly, is gocryptfs gonna work with those alternatives? Actually, it wonāt, because right now go-fuse depends explicitly on macFUSE.
So, I wasnāt ready to commit to that setup without having a somewhat viable fallback.
While FUSE, as we saw, is a bit of a challenge on macOS, itās perfectly fine on Linux. gocryptfs and FUSE on Linux are not going anywhere.
Now, Lima is a pretty sweet way to run a Linux VM on macOS. Similarly to WSL on Windows, Lima can drop you in a Linux shell on your Mac, with transparent access to your files.
This means you can easily install gocryptfs in that Lima environment,
and use it there. Assuming I want to get an encrypted mount of my home
directory (~
):
brew install lima
limactl start
lima sudo apt install gocryptfs
# Init in a temp dir because Lima can't write to the host filesystem
lima gocryptfs -init -reverse /tmp/lima
# From the host move the config file in the right place
mv /tmp/lima/.gocryptfs.reverse.conf ~
lima mkdir -p /tmp/encrypted
lima gocryptfs -reverse ~ /tmp/encrypted
lima rsync --archive /tmp/encrypted "$DESTINATION"
Note: Depending on how you connect to $DESTINATION
, you may want to
copy/link your SSH config and keys inside the Linux home of the VM
user. For example:
lima ln -s ~/.ssh/{config,id_ed25519*} "$(lima sh -c 'echo $HOME')/.ssh"
We can as easily do the opposite: use SSHFS to mount the remote encrypted directory locally, then use gocryptfs to decrypt it and access the files transparently.
lima sudo apt install sshfs
lima mkdir -p /tmp/encrypted /tmp/decrypted
sshfs -o idmap=user "$DESTINATION" /tmp/encrypted
gocryptfs /tmp/encrypted /tmp/decrypted
At that point we can browse the decrypted tree from the Lima shell, however we canāt access it from the host.
If Lima can access files from the host, why canāt the host access files from Lima?
Well, it comes down again to the ability to us FUSE. In order to access host files, Lima starts a SSHFS server on the macOS host, and then mounts it via SSHFS (FUSE) inside the Linux VM. Thatās fine, because Linux have absolutely no issue with FUSE stuff.
The other way around however, we would need FUSE on the macOS side in order to mount a SSHFS server running inside the VM. No bueno, because weāre doing all this jazz to avoid dealing with FUSE on macOS in the first place. š¬
So if weāre not gonna use FUSE, we need to fallback to another protocol thatās better supported on Mac, like WebDAV.
The best way Iāve found to do that is actually to use a simple, plain Go WebDAV server such as this one.
Just point the server to serve the decrypted mount point from earlier.
We also need to edit the Lima VM config in
~/.lima/default/lima.yaml
to forward the port the WebDAV server is
listening on, so we can access it from the host system, such as:
portForwards:
- guestPort: 1234
Then on the macOS side we can do:
mkdir -p mountpoint
mount_webdav http://localhost:1234 mountpoint
Before going with the custom Go solution, Iāve tried phį»dav, because unlike most WebDAV servers, it doesnāt require any kind of hairy configuration, and can be spawned in a ad hoc way that just works. But the performance wasnāt as good as the Go version. Iāve also tried NFS, but that was much even slower.
That said, donāt get your hopes too high. Even with the Go version, the performance wasnāt super fast, but I believe itās mainly because of being run over SSHFS, so your mileage may vary depending on the network bandwidth you have with your offsite server. But as a fallback, Iāll call it good enough anyway.