Mounts are a runtime dependency.
FUSE, NFS, FSKit, permissions, daemons, and platform-specific setup become part of the application you are trying to ship.
File infrastructure for modern applications
When your product needs paths, handles, directories, and sync semantics, mount-rs gives you a stable Rust and Node contract for direct access—or a real mounted filesystem through FUSE, NFS, 9P, or FSKit. HTTP and WebDAV provide network edges when a mount is not the right fit, while namespace metadata and immutable blocks stay explicit and replaceable.
Open source · Apache-2.0 · prerelease · evidence-led
one contract / explicit choices
The problem
A mount can work on one laptop and still be the wrong boundary for a container, serverless process, desktop app, or Node service. The hard part is not reading a file. It is keeping namespace, bytes, lifecycles, and deployment choices coherent.
FUSE, NFS, FSKit, permissions, daemons, and platform-specific setup become part of the application you are trying to ship.
Namespace and revisions need publication and fencing. Object or block storage needs immutable bytes and durable barriers. Mixing the two makes failure behavior difficult to reason about.
Switching from local files to SQLite, a database service, or an object store should not require rewriting every file operation in the product.
The mount-rs answer
mount-rs keeps the core small and makes the boundary visible: use the API directly, create a real mount for a host, or put HTTP/WebDAV at the edge. Choose where namespace metadata lives and where immutable blocks are stored independently.
Use paths, handles, stats, directory operations, and explicit sync behavior from Rust or Node.
Explore the core APICompose a metadata provider with an immutable block provider, then flush blocks before publishing references.
Compare providersCreate a real filesystem mount with FUSE, NFS, 9P, or FSKit where the platform integration is available; use HTTP or WebDAV when the edge is networked.
Choose the edgeThe storage model
The same file operation crosses a namespace plane and an immutable block plane. This conceptual view makes the ordering visible without pretending every provider uses the same physical schema.
Illustrative provider view
/reports/q3.pdfnamespace:
path: /reports/q3.pdf
revision: 7
size_bytes: 131072
blocks: [block_01, block_02]
block_01:
key: files/7/block_01
bytes: 65536
immutable: trueMetadata carries inode attributes, directory entries, and block references. It does not carry the file bytes.
Keep inode attributes, directory entries, and block references in the metadata contract. The namespace points to bytes; it does not become the byte store.
Chunk the file according to its layout, write immutable blocks, and wait for the block-store barrier before metadata can refer to them.
Publish with revision CAS and a monotonic writer fence, then complete the metadata barrier before the write is acknowledged.
Operational boundary: ownership loss fails closed. An uncertain commit can leave unreferenced blocks; automatic GC and copy-on-write are not implemented yet.
How to use it
Begin with a direct loopback contract, choose the storage planes your workload needs, then either create a real mount for the host or expose a network transport. The application contract stays the same while the edge changes.
Give your application file operations without requiring a kernel mount.
Keep namespace and immutable bytes explicit so each provider has one job.
Create a real mount through FUSE, NFS, 9P, or FSKit when the host needs a filesystem; choose HTTP or WebDAV for a network edge.
let fs = Loopback::new(MemoryFs::new(MemoryOptions::default()));
fs.write_file("/hello", b"hello").await?;
let bytes = fs.read_file("/hello").await?;const fs = await createChunkedDriver({
metadata: { kind: 'sqlite', uri: './metadata.sqlite' },
blocks: { kind: 'sqlite', uri: './blocks.sqlite' },
chunkSize: 65536,
});
await fs.writeFile('/hello', Buffer.from('hello'));Choose the boundary
mount-rs is a choice for teams that want file semantics without making a platform mount or one storage service the product API. It is not the right abstraction for every workload.
If callers already work in buckets, keys, immutable objects, and provider-native lifecycle rules, adding filesystem semantics may create more surface area than it removes.
Review the storage rolesFUSE, NFS, 9P, and FSKit put the filesystem surface back into a host when users or existing software expect a mounted path. Platform permissions, daemon lifecycle, and qualification remain part of that choice.
Compare transportsWhat changes for your team
Proof, not promises
mount-rs is a prerelease project. The docs separate repository implementation, local tests, and live provider evidence so you can make an informed adoption decision.
FsDriver and FileHandle contracts.Make the boundary explicit