This turned out easier than i was expecting it to be. It's nice to be able to mount a VFS without needing privileges on the server side.
The main intention for this code is to eventually use it to replace fuse on mac, since nfs is a valid mount time for mac clients to consume.
This is great! SOOO useful to be able to do mounts w/o fuse, w/o kernel extension, w/o root. This is a HUGE UX thing, specially for macs.
Fuse is a really great idea & project, but sadly today impls require a lot of install steps in some platforms, and some have painful bugs/UX. Amazing if we can mount VFSes from Go without those hurdles.
- Under Linux and FreeBSD, bazil fuse offers a nice low dependency path to supporting FUSE. It is all pure Go code.
- Under Windows, you can use WinFSP, which is a rock solid usermode filesystem driver with FUSE support. Despite its name, you can use this with Cgofuse to get FUSE on Windows without CGo.
Combining the two above gets you pretty far already (though if you want to actually avoid a CGo dependency you do need to explicitly disable it.)
I think the next level would be to have a general filesystem interface (there are several options in the ecosystem already) that can be used as a common ground between different usermode filesystem and network filesystem server implementations. Then ideally, a magic Go library can exist that gives you the best possible setup with switchable backends depending on the platform and build configuration.
Right now Go itself is possibly standardizing a read-only filesystem interface, an extension of this with write support might serve as a decent jumping point for getting toward an idealized pluggable filesystem library.
It won't be enough for the likes of FUSE, though. Some extensions might be enough to bridge that gap, it's too early to tell. FUSE is pretty particular about things like rename(2) preserving node identity.
The fuse replacement is super interesting. So you’d basically have a user space utility that provides NFS<->fs bridging? Would you support the existing fuse API? What does NFS not allow that Fuse would, if anything?
one of the major attractions of the fuse abstraction layer is that once you have fuse you can interact with more exotic file system types without having to deal with new kernel drivers each time.
Instead though, you can translate the exotic file system types to nfs, and use the existing kernel drivers that already exist for mounting an NFS mount.
Very cool! With "only" 3.2k lines of code for a NFS implementation I was indeed surprised that it was so easy. As for the privileges, how do you deal with the issue of port 111 being a privileged port?
This is cool! At a previous company we got a lot of mileage in debugging and ad-hoc tasks by exposing various things as filesystems. We mostly did webdav, but NFS is way better from a client transparency perspective. For many folks find, ls, and grep very much beat curl and jq.
A nice protocol to do this with is 9p [1]. It's much easier to implement a server for it than for NFS, either from scratch or even with a good library, and it's about just as usable on major operating systems. It has a tiny API and therefore surface area, also making it great for high security applications. It’s probably the closest thing we have to a cross-platform, network transportable FUSE.
Even though it started its life as a component of Plan9, 9p is getting through a renaissance period right now: qemu, WSL, gVisor, ChromeOS VMs (crostini)... all use 9p!
Unfortunately all the default implementations really suck at performance (for Linux and Windows, at any rate), and it’s very noticeable under IO pressure, lots of small files, etc. They're stable and seem to be correct though, which is something.
9P is fine as kind of lowest common denominator network filesystem, as long as you don’t hit its fundamental limitations, such as not being particularly Unix-compatible, semantics wise.
Considering how many things have been implemented on top of HTTP, I find it interesting that something like WebDAV (or Solid[0], or remoteStorage[1]) hasn't nearly completely supplanted NFS/SFTP/etc.
Not saying that would be ideal from a technical perspective (WebDAV at least has some issues), just surprised the ability to access remote filesystems from the browser hasn't been a bigger driver.
For example, there are a lot of interesting apps built on top of Google Drive as the storage backend, but overall the concept doesn't seem to have gained much traction.
Almost all WebDAV implementations are a big pile of crap, and network filesystems in general are much more tricky than people realize. If somebody invents a brand new protocol that that actually works it would probably be adopted, but it would face at least as many problems as NFS does.
I don't really understand why people want network filesystems most of the time. If you try to pretend it's like real local i/o, and it's not on a perfect network, you will have a bad time. Protocols designed specifically just to transfer a file tend to be more resilient and also not expose people to the problems of programs trying to do file i/o.
I don't think you need to go full filesystem abstraction, a la FUSE. I completely agree trying to do something like access a git repo on a FUSE FS which is actually remote is going to be painful.
But just having a standardized way to do directory listings, uploads, partial writes, auth, etc over HTTP would be useful to me.
Windows 10 has a new API just for this, the integration with OneDrive (apart from being extremely obtrusive/pressuring me into use something I don’t want) works great.
It’s basically a shell component that abstracts over file selection for open/save and an api for providing the list of files, reading or writing files/parts of files, and shims around common fs operations like copy and move.
Mostly target audience, I'd imagine. Anyone still using NFS or iSCSI probably has specific performance or integrity requirements that those services aren't geared for, plus multiple concurrent access that makes locking and cache coherence significant questions.
In terms of low-urgency storage though, the Dropbox/Google Drive/Syncthing model of directory replication largely has supplanted SFTP, though.
There is probably some middle group of S3/B2 type storage backing some FUSE-style integrated filesystem, but I'd suspect the same problem that makes WebDAV unpopular hampers that, namely that it almost invariably sucks horribly on Windows when it works at all.
Sun developed WebNFS [0] specifically so Java applets (remember them?) could access remote filesystems through firewalls from the browser. It's basically the same protocol as NFSv3 with some clever workarounds so that it doesn't require the separate MOUNT protocol to set up a connection (or the portmapper). That way everything runs on a single port.
I remember trying a few WebDAV implementations back in the day -- the performance was awful, and they were difficult to configure compared to a vanilla SSH or Apache/Nginx install.
Implementing on top of HTTP is usually to make things easier for users behind firewalls, squid proxies, and the like. In my experience, those environments (schools, offices) usually had to open port 21 and/or 22 for FTP/SFTP for a web maintainer anyway...
But NFS isn't a custom protocol for any specific app either, and apps that need good fs performance (eg databases, video editing platforms, "big data" compute platforms etc) avoid it.
Implementation-wise HTTP has the advantage that the apps can tune the client code because the protocol client implementation isn't in the kernel.
In addition HTTP security (transport & user authentication) is works and everyone understands it, whereas on NFS it's a huge mess and enemy of interoperability.
In practical popularity NFS fares extremely poorly eg on AWS (how many apps use EFS vs S3).
But S3 also charges $5/million object writes (and 40¢ for reads), but EFS is "free" (factoring burst capacity, per-instance maximum throughput limits, etc).
Couple that with EFS' lifecycle migration allowing you to get storage costs as low as 2.5¢/GB for many write-once-read-(almost)never after 7 day applications, things get a lot more complicated.
Yeah, that's what I was alluding to by saying it would likely not be ideal from a technical perspective. But raw TCP with a custom protocol is faster also, and yet many (most? all?) mobile apps use HTTP+JSON, even if they don't have a web app to support.
Most internet applications use HTTP because real networking is a pain, designing a custom protocol correctly is difficult, and HTTP provides enough functionality and flexibility to munge network traffic any way you want. They use JSON because it's the least pain in the ass of all the data formats.
Custom protocol over UDP is the fastest, which NFS supports, so NFS is basically the fastest (unless you get into wonky multiplex-streamed custom apps). However, UDP apps do not often work well through firewalls.
I feel like I'm fairly familiar with the tradeoffs. I'm simply making an observation that it's interesting to me that filesystem access over HTTP isn't bigger than it is.
> filesystem access over HTTP isn't bigger than it is.
I don't think it's a trade-off thing. It's conceptual;
FS over HTTP is not bigger than it is because filesystems are a much more stateful concept that often has to support coordinative transactions (like locks) whereas HTTP is a stateless protocol by design, so there's fundamentally a mismatch. That's why HTTP is better matched for an object system like S3 which is capable of being transported over stateless links and gives fewer coordination guarantees and is only eventually consistent.
You can support locks for HTTP if you need them (WebDAV does), though I would argue they aren't necessary for a large number of useful tasks.
You don't have to implement all the semantics of a filesystem in order to benefit. The main benefit comes from making a filesystem-like construct accessible in the browser. As I said before, Google Drive is a good example of this (and it's an object system, so that's an orthogonal issue), but it's a complicated protocol (as is S3) in a walled garden.
NFS is a really slow churning wheel. I think you’ll probably first see an inefficient generic option to tunnel tcp over quic (on both ends) that someone will hack to support nfs before you see an NFSv5 with quic support.
NFS is not particularly married to UDP though, unless we're talking about old timey NFSv2. There was even a WebNFS spec back in the day designed to let Java applets mount stuff over the internet.
Because WebDAV implementations aren't that good and a true pain in the butt for system admins to setup. If someone made one that was half as easy to setup as say PHP, it would be doing really well right now.
Didn't see it mentioned in the README, so I'll ask here: any particular reason to go NFSv3 vs NFSv4? I'm not familiar enough with the protocol to venture an educated guess.
V4 has many more things going on (it's stateful, has a much more complicated locking system integrated, and adds some other points of complexity that get better performance).
More than I was ready to take on for a first pass :)
For what it's worth, stateful is a good thing; NFSv4 leases are what allows it to safely do more aggressive caching than NFSv3. Back when it was new, benchmarks showed a good speed increase all around...
When looking for something like this a year or so ago, I found [1] which supports both NFSv3 and v4 as well as p9. It worked alright in my experience though I eventually switched to ZFS which has built in support to auto-configure NFS shares.
Most testing has been on a Lan or on the local machine for local VFS use cases.
This layer eschews responsibility for multiple concurrent clients for simplicity. No promises you'll get either decent performance or proper cache invalidation when using it that way. It tends to be conservative in not filling in all the opportunistic caches.
There's a hook the backing application can use to tune reads and write sizes that becomes much more relevant in a network case. How those should be set in practice isn't something I've spent time on.
I wonder if this is a good way to support projects like Microsoft's Git VFS without requiring specific kernel drivers. Mounting a special Git NFS drive + having all the magic hidden behind NFS seems like it could be interesting.
I've always wondered if I could take the Unix "everything is a file" approach way too far and hook it up to a web service. This looks like exactly the kind of glue to make that easy...
My favorite "everything is a filesystem" hack from around 2001 was cdfs for Linux, which would expose each audio track as a .wav file you could cp, and each separate data session as a subdirectory, so you could access prior states of the CD filesystem.
This turned out easier than i was expecting it to be. It's nice to be able to mount a VFS without needing privileges on the server side. The main intention for this code is to eventually use it to replace fuse on mac, since nfs is a valid mount time for mac clients to consume.