It's a Tuesday morning and the on-call engineer is staring at a directory that won't list. The mount is there, the SSH session is up, the disk has space, and ls is hanging. Five minutes ago an automated job wrote a file to that directory. The kernel says the mount is active. The userspace says nothing at all. Someone in chat asks the question that comes up in every shop running sshfs at scale: why are we still using this?
This post is for anyone who's been there. Anyone who's run sshfs in production, or curlftpfs, or piped a tarball through lftp, or tried to treat a GVFS mount as a real filesystem and watched a downstream tool refuse to read it. The open-source Linux mounting story is full of tools that work great in a demo and fall over in a real fleet. ExpanDrive's answer comes at the end of this post. Most of what follows is just naming, honestly, what's actually wrong with the alternatives.
The sshfs failure modes anyone running it has hit
sshfs is the FUSE-over-SSH classic that ships in every package repo. It's lovely for a one-off mount on a workstation. At scale, the problems start showing up in the same five places every time.
SSH connection limits. Every sshfs mount holds an SSH session open. The remote sshd has MaxStartups and MaxSessions configured (often 10/10 by default). A few servers each holding a mount, plus the human SSH logins, plus the Ansible runs that touch the same host, and you're hitting the cap. New connections start failing with kex_exchange_identification: Connection closed by remote host. The mount you already have keeps working until the SSH session dies, at which point the mount turns into a zombie.
The zombie mount. Transport endpoint is not connected. Every sysadmin has typed those words into a search bar. The remote side dropped, the local side didn't notice, the kernel still thinks the mount is there. ls hangs, umount hangs, fusermount -u hangs. The fix is usually umount -lf or a reboot of the box, depending on which child process is still holding the FD. It is not pleasant, and it happens every time the network blips for more than the SSH keepalive window. Nobody has time to tune keepalives on every host.
Cache invalidation. sshfs has a default attribute cache (-o cache_timeout=20) so it doesn't stat every file on every read. A process writes to the remote side over a different connection — a CI job, a partner upload, another machine in the fleet — and your local sshfs mount returns the stale metadata until the cache expires. Twenty seconds is a long time when you're debugging a build pipeline. Turning the cache off makes performance worse; leaving it on makes correctness worse. There's no good answer.
Multi-megabyte stalls on small writes. Edit a 200-byte file inside a large directory and sshfs sometimes pulls the entire directory contents to re-validate. Subjectively, you saved a one-line change and watched it take 90 seconds. Objectively, the protocol round-trips are doing exactly what they're configured to do. Either way, the user-facing experience is Linux mounts are slow.
The sftp channel itself is not a filesystem protocol. SFTP was designed for interactive file transfer. It carries metadata, but its semantics around O_APPEND, locking, partial writes, and atomic renames don't match what userspace tools expect from a real filesystem. Most things work most of the time, until they don't, and when they don't the failure modes are weird (databases corrupting their journal files, archives extracting with truncated members, log rotation losing the last few lines). These bugs are subtle and the root cause is almost never the application's fault.
The other open-source mounts
sshfs is the famous one. The alternatives are worse:
curlftpfs is a FUSE wrapper around libcurl's FTP support. It works for a small directory tree. On large directories — more than a few thousand entries — it has a long history of crashes and out-of-memory kills. The project hasn't seen a real release in over a decade. Most distributions still ship it because it has no replacement on the FTP side. It is a tool you'd pick because the alternative is no tool at all.
lftp is a great interactive FTP/SFTP shell with scripting. It is not a filesystem and was never trying to be. You can drive it from a shell script to upload and download files. You cannot point vim at it, you cannot point grep at it, you cannot point a build system at it. Every team that tries to use lftp as a sync engine eventually rebuilds half a filesystem in bash and regrets it.
GVFS is GNOME's "virtual filesystem" layer. It works inside Nautilus, the GNOME file manager, and inside applications that link the GIO library. It does not present a real POSIX mount that arbitrary programs can read. A path under ~/.gvfs/sftp:host=example.com/ looks like a filesystem to Nautilus and looks like an empty directory to find, grep, and every CLI tool that uses open(2) directly. The "is it a real mount or a GIO façade?" inconsistency is the worst kind of bug — it's invisible until the wrong tool hits the path.
Plain sftp (the OpenSSH command, not sshfs). Fine for interactive use, fine in shell pipelines that read from stdin. Falls apart in any script that wants random access to the remote tree. You end up writing mget/mput loops and dealing with the fact that sftp's batch mode doesn't propagate errors usefully. Most automation that uses sftp ends up being one bug away from silently failing.
rclone mount is the modern alternative that gets the most credit. It does what sshfs does, but for ~60 cloud providers, and the FUSE implementation is meaningfully better. The trade-off is that rclone is a CLI tool first, and the mount feature is a side project for the maintainers. There's no signed package, no auto-update, no GUI, no systemd integration that survives a restart cleanly, and no commercial support if something breaks during business hours. For a power user it's the right pick. For a fleet, you're back to building your own packaging and deployment story.
What a real Linux cloud mount has to do
Walking back from the failure modes, the requirements aren't actually that obscure:
Stay mounted across network blips. The SSH or HTTPS connection underneath should be able to drop and reconnect without the mount going to zombie state. Kernel-side FUSE has the primitives to do this; the question is whether the userspace daemon uses them correctly.
Survive laptop sleep. A developer closes the lid, walks across the office, opens the lid. The mount has to be there. Without that, mount-as-drive on a laptop is a non-starter.
Cache reads aggressively, invalidate them on writes. Performance and correctness are both real. A mount that caches everything and never invalidates returns stale data. A mount that caches nothing is slow enough to make people stop using it. The right answer is a cache that knows the difference between read-mostly and write-mostly paths and tunes itself accordingly.
Survive scripted access. Mount a bucket, run a find across it, pipe the results to xargs grep. This has to work. Half the value of mount-as-drive is letting the standard Unix toolchain do its thing against cloud data. If the mount only behaves under interactive GUI access, it's a half-product.
Install as a signed package. A fleet deployment story means signed .deb and .rpm packages, repo hosting, predictable upgrade paths. Not "build from source on each host" and not "wget the binary and trust me."
Have a CLI for the cases where you don't want a GUI. Headless servers, CI runners, scripted workflows — all of them need a way to mount a connection without clicking through a UI.
What ExpanDrive does instead
ExpanDrive on Linux is a paid commercial product, and what you're paying for is that the requirements above are met. Concretely:
The mount uses FUSE with a daemon that handles connection drops as a normal recoverable event, not as a fatal mount failure. The remote endpoint drops, the daemon backs off, the mount stays present. New reads block until the connection comes back, then proceed. No zombie mount, no umount -lf, no reboot. A laptop sleeps and wakes; the daemon notices, reconnects, the mount keeps working.
The cache is a real cache with write-through invalidation. Reads against unchanged files return from local SSD. Writes propagate to the remote side and invalidate the cache locally so the next read gets the new content. The cache size is configurable. Pin-for-offline marks specific folders as always-resident, which solves the latency-on-random-reads problem for the hot subset of data without you having to clone the whole bucket.
Packaging is signed .deb and .rpm files with auto-update enabled by default. The Linux install is the same shape as the macOS and Windows installs — one package, one launch agent, one systemd unit. Ansible / Salt / Chef can deploy ExpanDrive to a fleet the same way they deploy any other agent.
The exfs CLI is the scripted-workflow story. Mount a connection, list connections, unmount, configure caching policy, all from the shell. CI runners that need a cloud mount for a build step can exfs mount s3://my-bucket /opt/build-input at the start of the job and exfs unmount at the end.
ExpanDrive isn't a magic fix for the SFTP protocol itself — partial writes are still partial writes, and the cache invalidation problem still has tradeoffs at the edges. But the operational footprint is the difference between a tool that the team trusts to be there in the morning and a tool that gets the on-call paged twice a week.
Where the open-source mounts are still the right call
To be fair:
One-off interactive use on a workstation. sshfs is exactly right for this. You're connecting to one remote, you trust the connection, you want a quick mount for the next hour. Install from apt, run the command, get back to work. ExpanDrive is overkill for the use case.
Air-gapped or strict-no-commercial environments. Some environments have a hard policy against commercial userspace daemons. The open-source mounts are what you have. The trade-off is that you also have all the failure modes above, and the team is on the hook for working around them.
Hobby and personal projects. ExpanDrive is paid software. For a personal Nextcloud or a homelab S3-compatible bucket, the cost might not be worth it. The open-source mounts work; they just don't scale.
Pure object-store access from a single process. If the workload is one Python program reading from S3, just use the boto3 SDK directly. You don't need a filesystem; you need an HTTP client. Mounting buys you nothing.
What to do next
If you're running sshfs in production and the failure modes above sound familiar, the move is small: try ExpanDrive on one of the hosts that pages you the most. Free trial, signed package, two minutes to install. If the host stops paging, roll it out to the rest of the fleet. If it doesn't, you've lost two minutes.
Download ExpanDrive for Linux — .deb for Debian/Ubuntu, .rpm for RHEL/Rocky/AlmaLinux/Fedora, signed and auto-updating. The SFTP-on-Linux integration page covers the SFTP-specific setup if SFTP is the protocol you're replacing sshfs against.