embednfs
An embeddable NFSv4.1 server library in Rust. You implement a small filesystem trait; the library handles the wire protocol, sessions, filehandles, locking, and TCP serving.
The implementation target is Apple/macOS NFSv4.1 client compatibility first, with a localhost FUSE-replacement use case. The public API is intentionally opinionated and minimal.
Support Boundary
This project currently makes two important non-promises:
- It does not guarantee correct or robust behavior over a real network. The target deployment is localhost. Running it over non-localhost transport may work in some cases, but that is not a supported or validated use case.
- It does not guarantee correct behavior for non-macOS clients. The implementation and live validation target the macOS kernel NFSv4.1 client and Finder workflows. Other clients may work, but they are not a compatibility target.
In short: the supported target is macOS over localhost.
Architecture
This is a Cargo workspace with three crates:
embednfs-proto— XDR encoding/decoding and NFSv4.1 protocol typesembednfs— Embeddable server library with the filesystem traits and COMPOUND handlerembednfsd— NFSv4.1 server daemon powered by embednfs
Quick Start
use ;
async
Then mount:
# macOS
Note: on macOS, vers=4 means NFSv4.0. Use vers=4.1 explicitly.
Non-macOS clients are not a supported compatibility target, even if they happen to mount successfully.
Filesystem API
The filesystem API is handle-based and models the exported filesystem rather than the raw backing store. Weak backends such as exFAT- or S3-style adapters are expected to provide stable handles, exported attrs, and any overlay metadata they need behind the trait.
Core Trait
use async_trait;
use Bytes;
use ;
Key points:
Handleis opaque backend identity. It is not the NFS wire handle and not the exportedfileid.Attrscarries the exported metadata view, includingfileid,change, times, flags, and ownership.RequestContextis passed to every op so adapters can make explicit policy decisions.readdir()is paged and cookie-driven, with optional inline attrs forREADDIRhot paths.
Extension Traits
The server will use these when present:
Xattrsfor macOS named attributes / xattrs / named streamsSymlinksforCREATE symlinkandREADLINKHardLinksforLINKCommitSupportfor explicitCOMMIT
If an extension trait is absent, the server returns the appropriate NFS unsupported/type errors and does not advertise the feature where that matters.
Apple-Focused Operation Support
Implemented for normal Apple/macOS client flows:
EXCHANGE_ID,CREATE_SESSION,SEQUENCE,DESTROY_SESSION,DESTROY_CLIENTIDPUTROOTFH,PUTFH,GETFH,LOOKUP,LOOKUPP,SAVEFH,RESTOREFHGETATTR,ACCESS,OPEN,CLOSE,OPEN_DOWNGRADEREAD,WRITE,COMMIT,READDIR,SETATTRCREATEfor directories and symlinksREMOVE,RENAMELOCK,LOCKT,LOCKUSECINFO_NO_NAMEOPENATTRNVERIFYRECLAIM_COMPLETE,FREE_STATEID
Supported through extensions:
READLINKLINK- macOS named-attribute and xattr flows behind
OPENATTR
Kept as cheap compatibility ops:
SECINFOPUTPUBFHVERIFYTEST_STATEIDDELEGPURGEBIND_CONN_TO_SESSIONDELEGRETURN
Explicitly unsupported:
BACKCHANNEL_CTLGETDEVICEINFO,GETDEVICELISTGET_DIR_DELEGATIONLAYOUTGET,LAYOUTRETURN,LAYOUTCOMMITSET_SSVWANT_DELEGATION
Rejected in NFSv4.1 because they are v4.0-only:
OPEN_CONFIRMRENEWSETCLIENTIDSETCLIENTID_CONFIRMRELEASE_LOCKOWNER
Testing
The integration suite exercises the full RPC path over TCP and includes raw OPENATTR/named-attribute flows for macOS-style clients.
cargo test --workspace also runs a small foreign-client interoperability smoke lane through nfs-rs.
cargo test --workspace --test nfs_rs_stress -- --ignored runs a longer concurrent mixed-load stress workload through the same foreign client.
For a genuine localhost/macOS smoke test, scripts/smoke-macos-nfs41.sh starts embednfsd, mounts it with mount_nfs, exercises basic create/write/read/rename/remove/rmdir behavior through the kernel client.
Many of the protocol conformance tests are adapted from the maintained pynfs tree at git://git.linux-nfs.org/projects/cdmackay/pynfs.git.
License
MIT