Skip to content

feat: macfuse#11249

Open
wjmelements wants to merge 2 commits intoipfs:masterfrom
wjmelements:feat/macfuse
Open

feat: macfuse#11249
wjmelements wants to merge 2 commits intoipfs:masterfrom
wjmelements:feat/macfuse

Conversation

@wjmelements
Copy link
Copy Markdown
Contributor

Reviewer @lidel

  • osxfuse seems to be abandoned, and macfuse seems to be its successor.
  • seaweedfs/fuse supports both macfuse and osxfuse
  • plutil is installed with macOS, just like sysctl
  • mount seems to work with macfuse after these changes

Changes

  • switch dep from bazil.org/fuse to seaweedfs/fuse
  • handle 2.7.2 version check via plist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wjmelements wjmelements requested a review from a team as a code owner March 24, 2026 03:06
Copy link
Copy Markdown
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this @wjmelements, macFUSE support has been broken for a while and it's good to see someone poking at it.

I do not think we can merge this as-is, I want to share some context about the FUSE library landscape that affects which direction we take here.

The state of bazil.org/fuse

The current dependency (bazil.org/fuse) is maintained by Tommi Virtanen (tv42), essentially a one-person project. The last commit was January 2023, there are 62 open issues and 22 unreviewed PRs. macOS support was deliberately removed in April 2020 after OSXFUSE went closed-source. We're pinned to a Jan 2020 snapshot from before that removal. It's effectively abandoned.

The state of seaweedfs/fuse

seaweedfs/fuse was forked from bazil by Chris Lu (SeaweedFS creator) in December 2018. It added macFUSE 4.x support, some perf improvements, and a data race fix. The last commit was August 2023, and v1.2.3 is the latest tag. It is 36 commits ahead of bazil but roughly 200 commits behind .

⚠️ The critical issue: SeaweedFS itself has moved away from this library. ⚠️

As of January 2026, SeaweedFS uses seaweedfs/go-fuse (a fork of hanwen/go-fuse), a completely different FUSE library. The fork's own creator has walked away from it. Only about 17 packages import seaweedfs/fuse, almost all SeaweedFS forks.

This PR's seaweedfs/fuse swap is trading one abandoned library for another abandoned library. It solves the immediate macFUSE 4/5 detection problem but doesn't improve the long-term situation.

What the ecosystem is doing

The Go FUSE ecosystem has largely converged on two paths:

  • hanwen/go-fuse (2,300 stars, last commit March 2026, maintained by Han-Wen Nienhuys at Google) is the de facto standard. Used by gocryptfs, kopia, containerd, and rclone's newer mount2 backend. Has FUSE3 support and the best performance. SeaweedFS moved here. The downside: completely different API from bazil, so migration means rewriting kubo's fuse/ layer.

  • anacrolix/fuse (43 stars, last commit March 2026, maintained by Matt Joiner) is the most actively maintained bazil fork. It's API-compatible (drop-in replacement), supports macFUSE 4+, and adds FUSE-T support (kext-less macOS FUSE, which is where Apple is pushing things). Used by restic. No FUSE3 support, and restic acknowledges it as a stopgap, but it is actively maintained today.

For comparison:

Library Last commit Maintained bazil API compat macOS FUSE3
bazil.org/fuse Jan 2023 No -- No No
seaweedfs/fuse Aug 2023 No Yes macFUSE 4 No
anacrolix/fuse Mar 2026 Yes Yes (drop-in) macFUSE + FUSE-T No
hanwen/go-fuse Mar 2026 Yes No (rewrite) Yes Yes

What I think we should do

I appreciate the pragmatic approach here, but if we're going to touch the FUSE dependency, we should pick something that's actually maintained rather than swapping one dormant library for another. The tryMacFUSEPlist() addition for version detection is a good idea regardless of which library we use.

If the goal is "fix macFUSE with minimal effort now", anacrolix/fuse would be the better drop-in since it's actively maintained and also supports FUSE-T (which matters as Apple continues to deprecate kernel extensions).

But my personal opinion as a maintainer is that we should not do necromancy for macOS, unless there is clear benefit to ecosystem?

The proper long-term fix is migrating to hanwen/go-fuse, which is where the ecosystem has settled, but that's a bigger project and probably a separate effort. And adding proper end-to-end tests to test/cli (to replace legacy test/sharness) that run on both macos and linux (similar to how migration tests run on windows/macos/linux.

Thoughts?

@lidel lidel added need/author-input Needs input from the original author status/blocked Unable to be worked further until needs are met need/analysis Needs further analysis before proceeding labels Mar 24, 2026
@wjmelements
Copy link
Copy Markdown
Contributor Author

ok I picked seaweedfs/fuse because it seemed like it would require the least changes. However I understand your reasoning.

anacrolix/fuse would be the better drop-in

I definitely have time to do that if you would accept it.

The proper long-term fix is migrating to hanwen/go-fuse

I agree, but I am less sure that I will have time to do it.

@lidel
Copy link
Copy Markdown
Member

lidel commented Mar 25, 2026

@wjmelements ack, perhaps a good compromise and value add for now is going with anacrolix/fuse, if you have bandwidth for that. Does not have to be complete, as long you get it working for you locally, I can help with writing tests and adding them to CI on macOS runner (which we dont have yet).

So the next steps here would be:

Use anacrolix/fuse instead of seaweedfs/fuse

Pin to latest master commit (ahead of v0.3.2, has ARM O_LARGEFILE fix, race fixes, nil deref fix). Avoid v0.4.0 -- phantom tag cached by Go proxy then deleted.

Drop tryMacFUSEPlist() and clean up mount_darwin.go

iiuc anacrolix/fuse handles macFUSE 4.x detection internally (OSXFUSELocationV4) and adds FUSE-T support. Backend selection is automatic: FUSE-T > macFUSE 4 > macFUSE 3.

So the ancient version detection in fuse/node/mount_darwin.go (tryGFV, trySysctl, tryGFVFromFuseVersion, ensureFuseVersionIsInstalled) is dead code after the switch -- it protects against OSXFUSE 2.7.2 kernel panics from 2015, and anacrolix/fuse dropped OSXFUSE 2.x entirely. The error messages link to osxfuse.github.io (dead) and try to go install github.com/jbenet/go-fuse-version.

If anacrolix/fuse works, I think bunch of things could be removed from mount_darwin.go:

  • tryMacFUSEPlist() (new in this PR, not needed?)
  • trySysctl() -- reads osxfuse.version.number sysctl key, which macFUSE 4+ no longer populates
  • tryGFVFromFuseVersion() and ensureFuseVersionIsInstalled() -- tries to go install and run a third-party fuse-version binary
  • errStrFuseRequired, errStrNoFuseHeaders, errStrUpgradeFuse, errStrFailedToRunFuseVersion, errStrFixConfig, errNeedFuseVersion -- all reference OSXFUSE 2.7.2 and dead URLs
  • fuseVersionPkg constant
  • The semver check in darwinFuseCheckVersion against 2.7.2

What likely should stay (or be simplified?):

  • darwinFuseCheckVersion can either become a no-op or just verify that anacrolix/fuse can find a backend at all
  • dontCheckOSXFUSEConfigKey and userAskedToSkipFuseCheck if we want to keep the config escape hatch

Anyway, leaving the details up to you, as long things work on macOS.

Testing FUSE

Note that all CI runs TEST_FUSE=0 on Linux-only runners. No macOS CI.

This means this needs to be tested locally for now.
We can add macos runner that only runs FUSE tests before merging this PR, to ensure we dont have regressions.

test/cli (preferred)

This is where we add new end-to-end tests. It is better to add test here than to fix old one in test/sharness

make build
export PATH="$PWD/cmd/ipfs:$PATH"
export IPFS_PATH="$(mktemp -d)"
TEST_FUSE=1 go test -v -run TestFUSE ./test/cli/...

test/sharness (legacy)

Ancient test suite that we still keep around.

make build
export PATH="$PWD/cmd/ipfs:$PATH"
cd test/sharness
TEST_FUSE=1 ./t0030-mount.sh -v
TEST_FUSE=1 ./t0031-mount-publish.sh -v
TEST_FUSE=1 ./t0032-mount-sharded.sh -v

NOTE: if you run sharness, you may need to kill stale ipfs daemon processes between -v runs (verbose mode disables cleanup).

What to verify

Unsure, do we target the latest macOS? We usually do that for ipfs-desktop for Windows and macOS.

  • ipfs mount
    • with macFUSE 4/5?
    • with FUSE-T if installed (FUSE_FORCE_BACKEND=macFUSE to test both paths?)
  • Read via /ipfs/ mount, write+read via /mfs/ mount
  • Clean unmount on daemon shutdown

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

Labels

need/analysis Needs further analysis before proceeding need/author-input Needs input from the original author status/blocked Unable to be worked further until needs are met

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants