Skip to content
lollipopkitPublic

About

Mount SFTP/S3/Webdav/... to macOS via File Provider.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

MFuse

中文 | Download | License | Third-Party Notices

MFuse is a macOS app that exposes remote storage in Finder through File Provider, with a modular backend layer for multiple protocols.

Screenshots

MFuse app UI MFuse menubar status
MFuse mounted in Finder

Supported Backends

  • SFTP
  • S3
  • WebDAV
  • SMB
  • FTP
  • NFS
  • Google Drive (sign-in may be unavailable until Google approves the app)
  • Dropbox (temporarily unavailable)
  • Microsoft OneDrive (temporarily unavailable)

Dropbox and OneDrive are hidden in the app for now: release builds do not include their OAuth client IDs yet, so signing in cannot work. Existing connections of these types are kept but cannot connect.

Google Drive sign-in uses MFuse's OAuth app, which is still in Google's verification. Until it is approved, signing in may be refused or show an "unverified app" warning.

Backend Notes

  • SFTP directory enumeration has a compatibility fallback: when the normal SFTP listing path times out or hits certain connection-level failures, MFuse may execute a small python3 snippet on the remote host over the existing SSH session to enumerate the directory. This fallback is not used for normal successful listings, permission-denied errors, or missing-path errors. Remote hosts that hit this fallback must have python3 available, otherwise enumeration fails.
  • FTP uses passive mode only (EPSV, falling back to PASV); active mode cannot work behind NAT. With TLS on, port 990 uses implicit FTPS and any other port uses explicit FTPS (AUTH TLS); data connections are always encrypted (PROT P). Servers that require TLS session reuse on data connections (vsftpd's require_ssl_reuse=YES, FileZilla Server's default) are not supported yet: the TLS library MFuse uses cannot resume a session.
  • NFS is NFSv3 over TCP, through nfs.swift; NFSv4-only servers are not supported. Remote Path is the exported directory, which is mounted through the portmapper (port 111) and the MOUNT service. Requests carry AUTH_SYS with the UID and GID set on the connection, or the Mac user's own by default, and come from a port above 1024, which the File Provider extension cannot go below: a Linux export needs the insecure option (for example /srv/nfs *(rw,insecure,no_subtree_check)), or the server refuses the mount. NFSv3 has no server-side copy, so copies pass through the Mac. File names that are not UTF-8 keep their bytes; Finder shows those bytes as placeholder characters.

Project Structure

.
├── MFuse/                  # macOS app
├── MFuseProvider/          # File Provider extension
├── Packages/
│   ├── MFuseCore/          # shared models, storage, mount abstractions
│   ├── MFuseSFTP/
│   ├── MFuseS3/
│   ├── MFuseWebDAV/
│   ├── MFuseSMB/
│   ├── MFuseFTP/
│   ├── MFuseNFS/
│   ├── MFuseGoogleDrive/
│   ├── MFuseDropbox/
│   └── MFuseOneDrive/
├── project.yml             # XcodeGen project definition
└── Makefile

Getting Started

Requirements

  • macOS 14+
  • Xcode 15+
  • Swift 5.9+
  • XcodeGen
  • swiftlint for linting

Generate the Xcode project

make generate

Configure bundled OAuth apps

Google Drive, Dropbox and OneDrive use bundled PKCE OAuth app settings loaded from build settings (Dropbox and OneDrive are currently disabled in the app; see above). Set them in project.local.yml before running the app:

settings:
  base:
    MFGOOGLE_CLIENT_ID: YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com
    MFDROPBOX_CLIENT_ID: YOUR_DROPBOX_APP_KEY
    MFONEDRIVE_CLIENT_ID: YOUR_MICROSOFT_APP_ID

The Google client must be an iOS-type OAuth client with bundle ID com.lollipopkit.mfuse, with the Google Drive API enabled and the https://www.googleapis.com/auth/drive scope on its consent screen.

Default redirect URIs are already wired in the app bundle:

  • Google Drive: com.googleusercontent.apps.<client-id-prefix>:/oauth2redirect, derived from the client ID
  • Dropbox: com.lollipopkit.mfuse.dropbox:/oauth
  • OneDrive: com.lollipopkit.mfuse.onedrive:/oauth

Current scope:

  • Dropbox: standard user file space
  • OneDrive: the signed-in user's default personal/work drive

Out of scope for this first pass:

  • SharePoint document libraries and other non-default Microsoft Graph drives
  • Dropbox Team Space / admin impersonation flows

Run tests

make test

make test currently maps to test-stable and runs the stable local package subset. Use make test-all when you want the full package test matrix.

Lint

make lint

Build

make build

Release

make release

make release loads signing and notarization credentials from .env, computes the current git rev-list --count HEAD, and releases with:

  • MARKETING_VERSION=<MFUSE_BASE_VERSION>.<commit count>
  • CURRENT_PROJECT_VERSION=<commit count>

Example: when the commit count is 2 and MFUSE_BASE_VERSION=1.0, the release version becomes 1.0.2 and the build number becomes 2.

The release flow now expects:

  • a Developer ID Application certificate already installed in your macOS keychain
  • notarization credentials already stored via xcrun notarytool store-credentials
  • app and extension provisioning profiles already installed under ~/Library/MobileDevice/Provisioning Profiles
  • gh already authenticated for the target repository with upload permission

After notarization succeeds, make release automatically creates or updates the GitHub Release tagged v<MARKETING_VERSION>, sets its title to the same value, and uploads the generated DMG asset.

Testing

Current test coverage is centered on Swift packages, especially:

  • MFuseCore core models and connection management
  • MFuseFTP parser behavior
  • MFuseWebDAV XML parsing

Some backend tests are placeholders or integration-oriented, so protocol coverage is not uniform yet.

End-to-end tests

Packages/MFuseE2E runs the same file operations — create, overwrite, range and streamed reads, unicode names, move, copy, recursive delete — against real SFTP (password and key), FTP, FTPS (explicit and implicit), WebDAV, SMB, NFSv3 and S3 servers. It does not exercise the File Provider extension itself.

  1. Provision a Debian 13 host with scripts/e2e/setup-vm.sh, which installs OpenSSH, vsftpd, Samba, Apache WebDAV, the Linux NFS server and SeaweedFS (S3). Credentials are passed on stdin and never stored in the repository.
  2. Put the matching MFUSE_E2E_* settings in ~/.config/mfuse/e2e.env (see the variables setup-vm.sh reads). Copy the host's test CA certificate, /etc/mfuse-e2e/ca.pem, and point MFUSE_E2E_CA at it; the FTPS tests trust it only inside the test process. Set MFUSE_E2E_NFS_UID and MFUSE_E2E_NFS_GID to the test user's ids on the host (id -u, id -g).
  3. Run make test-e2e. Without MFUSE_E2E_HOST the tests are skipped.

HTTPS WebDAV is not covered yet.

License

MFuse is licensed under the GNU Affero General Public License v3.0. See LICENSE.

Third-party dependencies remain under their own licenses. See THIRD_PARTY_NOTICES.md for the current dependency notice summary.

About

Mount SFTP/S3/Webdav/... to macOS via File Provider.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages