nfsserve: a Rust NFSv3 server for cross-platform user-space mounts
A Rust NFS Server implementation
At a glance
- What is it?
- nfsserve implements the NFSv3 server side in Rust so a user-space filesystem can be mounted on Linux, macOS and Windows through the operating system's own NFS client. It is incomplete, the README says so, and it is used in production by Hugging Face's hf-mount.
- Who is it for?
- Adopt nfsserve if you are building a user-space filesystem that must be mountable on all three desktop operating systems and you want to reuse the OS NFS client instead of shipping a FUSE driver, since that is the specific gap the project sets out to fill. Steer away if you need NFSv4, link creation, or a complete protocol implementation, because the README lists those as open work, and READDIR is not implemented even though Windows always tries it first.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is the FUSE driver, not the filesystem
nfsserve is an incomplete but functional implementation of an NFSv3 server in Rust. The README explains the motivation with a question and three answers, and the reasoning matters more than the feature list.
The goal was a user-mode filesystem mount that is genuinely cross-platform. The question asked is what protocol nearly every operating system supports, and the answer is NFS. The reasons given for not using FUSE are specific: FUSE is annoying for users on Mac and Windows because drivers are necessary, building a FUSE driver for remote filesystems takes a lot of care, and NFS clients have a long history of hardening for slow-responding or never-responding servers while the operating system is already good at caching NFS, with established principles for cache eviction, metadata and data that a FUSE driver author has to rebuild.
So the shape of the project follows from that. It is described as a FUSE-like user-mode filesystem API that basically works by creating a localhost NFSv3 server you can mount. The user implements a trait, the library speaks the protocol, and the OS does the caching and the mounting.
The project is used in hf-mount to provide the hf-mount functionality, which is the strongest signal available about its fitness. The primary language is Rust, the licence is BSD-3-Clause, the crate version in Cargo.toml is 0.11.0, and the last push was on 2026-10-20.
Building the demo and mounting it on each platform
The demo filesystem can be built and run with the demo feature enabled, and it hosts an NFS server on localhost:11111:
cargo build --example demo --features demo
./target/debug/examples/demoThe mount side differs per operating system, and the differences are the point of the project. On Linux, where sudo may be required:
mkdir demo
mount.nfs -o user,noacl,nolock,vers=3,tcp,wsize=1048576,rsize=131072,actimeo=120,port=11111,mountport=11111 localhost:/ demoOn macOS:
mkdir demo
mount_nfs -o nolocks,vers=3,tcp,rsize=131072,actimeo=120,port=11111,mountport=11111 localhost:/ demoOn Windows, which needs Pro because Home does not have an NFS client:
mount.exe -o anon,nolock,mtype=soft,fileaccess=6,casesensitive,lang=ansi,rsize=128,wsize=128,timeout=60,retry=2 \\127.0.0.1\\ X:The Windows options are visibly different in kind from the others. It uses soft mount type, a small rsize and wsize of 128, and a timeout with a retry count, which is what a client does when it expects the server to disappear. The Linux and macOS options use a 1 MB write size and a 128 KB read size with an attribute cache timeout of 120 seconds.
One detail worth flagging is that the demo filesystem is writable, so a mounted demo is a live mount point on the local machine rather than a read-only sample.
Implementing the vfs::NFSFileSystem trait is the whole integration
The usage section is short because the integration surface is narrow. You implement the vfs::NFSFileSystem trait, with demofs.rs given as an example and bin/main.rs shown as how to start a service. The README says the interface is generally not difficult to implement, and that what it demands mainly is the ability to associate every filesystem object, directory or file, with a 64-bit ID. Directory listing is called out as the harder part because of the pagination requirements.
The reason for the 64-bit ID requirement is spelled out later in the NFS basics section. Every filesystem object, whether a directory, file or symlink, has two ways in which it can be addressed: a fileid3, which is a 64-bit integer equivalent to an inode number, and an nfs_fh3, a variable opaque object up to 64 bytes long. The client needs an nfs_fh3 any time it accesses information about an object, and the file handle serves two purposes, one of which is to allow the server to cache additional data. So the ID you supply in your trait implementation is what the protocol hands back to the client as the object address.
Two examples ship with the crate. The demo example is the in-memory one you mount to try the server, and a second example named mirrorfs sits alongside it, both gated behind the demo feature in the manifest, which is why the build command needs the feature flag at all.
Where NFSv3 and the Windows client fall short
The TODO section is the most useful part of the README for anyone evaluating this, and it is candid. The project is described as incomplete, and the list of open work includes improving the documentation and implementing more of the Mount Protocol and NFS Protocol.
The specific gap that bites in practice is READDIR. The README explains that a bunch of messages reply as Unavailable, and gives the example that READDIR_PLUS is implemented but READDIR is not, which is usually fine except that Windows insists on always trying READDIR first. Link creation is also not supported. The RPC message handling in nfs_handlers.rs is said to leave a lot to be desired, with response serialization being very manual and in need of cleanup.
Windows gets its own entry. The Windows mount is described as kinda working, only on Windows 11 Pro with the NFS server, and it prints a lot of garbage due to various unimplemented APIs, with Windows 11 somehow trying to poll with very old NFS protocols constantly. On the performance side there are many optimizations still to do, and NFSv4 is listed as having write performance optimizations that would be nice but that the protocol is more involved to implement since it is somewhat stateful.
The portmapper is described as a very old mechanism that is rarely used anymore, and the README notes it is not strictly necessary because NFSv4 does not use it and because Linux and Mac built-in clients do not need it when port and mountport options are specified. It was kept for debugging because libnfs seems to require a portmapper, although the source was modified to change the hardcoded port 111 to 12000 for testing, with one PMAPPROC_GETPORT method implemented.
The Windows limitation is the one that decides adoption for a lot of teams, since Home edition has no NFS client at all, and an SMB3 implementation is listed as a maybe for that reason.
The protocol stack is implemented by hand against the RFCs
The source layout shows the work involved, and the crate is written in Rust with tokio for the async runtime, using the net, io-util, sync, fs, rt and macros features with default features off. The other dependencies are byteorder, num-traits, num-derive, tracing, anyhow, async-trait and filetime.
The file list maps onto the protocol stack. context.rs holds a connection context object passed around with connection information and VFS information. xdr.rs is the serialization and deserialization for XDR structures, rpcwire.rs reads and writes RPC messages from a TCP socket and does the outer most RPC decoding before redirecting to the NFS, Mount or Portmapper implementations, and rpc.rs defines the structure of an RPC call and reply, all XDR encoded. Then portmap.rs and portmap_handlers.rs cover the Portmapper protocol, mount.rs and mount_handlers.rs the Mount protocol, and nfs.rs and nfs_handlers.rs the NFS protocol itself.
The relevant specifications are listed: XDR is the message format at RFC 1014, SUN RPC is the RPC wire format at RFC 1057, NFS is at RFC 1813, the NFS Mount Protocol is Appendix I of the same document, and the Portmapper is Appendix A of RFC 1057.
The message flow is described in six steps. A collection of fragments is read off the TCP stream, being a 4 byte length header followed by a bunch of bytes, the fragments are assembled into a record, the record is a SUN RPC message type, and the message tells you the RPC program, which is an integer denoting a protocol class, with the NFS protocol at 100003 and the Portmapper at 100000, the version of that program, where 3 is NFSv3 and 4 is NFSv4, and the method invoked. Decoding the message further gives the method arguments, and the response is wrapped back into a record and returned.
How this differs from a FUSE driver
The alternative worth comparing is not another Rust NFS server, it is the FUSE route the README argues against, and the difference is where the complexity sits.
With FUSE, your filesystem implements a kernel-facing interface, and the driver has to deal with the parts of the stack that the kernel would otherwise handle: caching, attribute management, page cache behaviour, and the difference between the local machine's conventions and the remote source's. The README's third reason is that the operating system is pretty good at caching NFS, with established principles for cache eviction, metadata and data, and that with a FUSE driver all of that work falls on you.
With nfsserve, you implement a filesystem trait and the OS NFS client does the rest. The client you inherit is the same one that has been talking to NFS servers for decades, including the hardening for slow-responding or never-responding servers that the README cites as a reason to prefer NFS over FUSE for remote filesystems. The mount options in the demo show the resulting behaviour, with an attribute cache timeout of 120 seconds on Linux and macOS and a soft mount with a timeout on Windows.
The trade is that you give up the FUSE-specific reach. FUSE works on any platform with a FUSE implementation, while this route needs an NFS client in the OS, which is why Windows Home is excluded. And you give up the ability to present semantics the NFS protocol cannot express, which is the practical reason the project notes that NFSv4 would be more involved to implement.
There is also a second product framing. The crate is not only a library for third-party filesystems: it exists because Hugging Face needed to mount a model store as a filesystem on any of these platforms, and the same code path is what hf-mount uses.
Editorial conclusion
Adopt nfsserve if you are building a user-space filesystem that must be mountable on all three desktop operating systems and you want to reuse the OS NFS client instead of shipping a FUSE driver, since that is the specific gap the project sets out to fill. Steer away if you need NFSv4, link creation, or a complete protocol implementation, because the README lists those as open work, and READDIR is not implemented even though Windows always tries it first. Before you build on it, read the TODO section and check the version in Cargo.toml, which is 0.11.0 with no published GitHub release, and note that the last push was on 2026-10-20.
Frequently asked questions
What is nfsserve and why not use FUSE?
nfsserve is a Rust implementation of an NFSv3 server, so a user-space filesystem can be mounted through the operating system's own NFS client. The README argues against FUSE because it needs drivers on Mac and Windows, is harder to build for remote filesystems, and leaves caching and metadata handling to the driver author.
How do I run the nfsserve demo?
Build it with cargo build --example demo --features demo and run ./target/debug/examples/demo, which hosts an NFS server on localhost:11111. You then mount it with mount.nfs on Linux, mount_nfs on macOS, or mount.exe on Windows Pro, using the port and mountport options shown in the README.
Which NFS operations are not implemented in nfsserve?
The README says a bunch of messages reply as Unavailable, and that READDIR_PLUS is implemented while READDIR is not, which causes trouble because Windows always tries READDIR first. Link creation is also unsupported, and the Windows mount prints a lot of garbage from unimplemented APIs.
Is nfsserve suitable for production use?
It is used in hf-mount to provide the hf-mount functionality, and the crate version in Cargo.toml is 0.11.0 with a BSD-3-Clause licence. The README still describes it as incomplete, lists a long TODO section, and the repository has no GitHub releases, so you should expect to track the main branch.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/huggingface-nfsserve)Was this useful?