Skip to content
LimniFS
All posts

LimniFS v0.1.0 — A Pure-Rust Content-Addressed Filesystem

LimniFS Teamreleasefilesystemrust

Today we’re releasing LimniFS v0.1.0 — a content-addressed, compressed, immutable filesystem image format written in 100% pure Rust.

LimniFS packs directory trees into a single .lim file with BLAKE3 content addressing, per-content-class compression, and Merkle-rooted integrity. It’s designed for archival, distribution, and cold storage — and it’s faster than DwarFS.

Why another filesystem format?

Every existing format makes trade-offs we didn’t like:

  • tar.gz / tar.xz: universal but no random access, no content addressing, no integrity beyond per-block CRC.
  • SquashFS: mature but requires kernel support or FUSE, uses C code, and isn’t content-addressed.
  • DwarFS: excellent ratio and speed but a C++ codebase with complex build dependencies, not suitable for air-gapped or fully-reproducible builds.
  • OSTree / casync: designed for different use cases (system updates, incremental sync), not for standalone image distribution.

LimniFS is what we wanted: a format where identity is content (BLAKE3), compression is per-content-class (text gets ZSTD, binary gets LZ4, random gets stored), integrity is Merkle-rooted (one hash verifies everything), and the entire implementation is pure Rust with zero C dependencies.

What’s in v0.1.0

Seven codecs, all pure Rust

Codec Encode Decode Use case
Store yes yes Incompressible data
LZ4 yes yes Fast tier
ZSTD yes (L1) yes General purpose
Brotli yes (q11) yes Best text ratio
DEFLATE yes (L6) yes Universal interop
Snappy yes yes Data lake / OLAP
XZ/LZMA2 decode-only yes Legacy archive decode

Adding a codec is one new file + one register() call — the dispatch code never changes. This is the open/closed principle applied to compression.

Performance vs DwarFS

Benchmarked against DwarFS 0.15.6 on a 440 MB text corpus:

Operation LimniFS DwarFS Ratio
Create 0.62s (700 MB/s) 1.00s 1.6x faster
Extract 0.59s (8500 files/s) 1.37s 2.3x faster
Image size 8% smaller baseline

The parallel writer (rayon) and the seine content classifier are the key accelerators: chunks are classified and routed to the optimal codec in parallel, with BLAKE3’s rayon feature handling hashing.

Content-addressed drops

Every piece of content — every file chunk — is identified by DropId = BLAKE3(plaintext). The codec, encryption, and erasure coding are representations, never part of identity. This means:

  • Identical chunks deduplicate automatically across files and images.
  • Re-encoding with a different codec doesn’t change identity.
  • Content integrity is verified by recomputing BLAKE3, not by trusting metadata.

Merkle-rooted manifest

The manifest’s root hash commits to the entire image. One signature (Ed25519, behind the signing feature) verifies everything — the drop store, the metadata tree, the slab index, the feature flags, the history.

Feature-flagged crypto

Each security capability is behind a Cargo feature flag, so the default build stays sovereign:

  • key-wrap: HPKE X25519 key wrap for sealed master keys
  • signing: Ed25519 manifest signing
  • http: HTTP/S3/IPFS locators for remote slabs
  • fuse: FUSE mount for read-only filesystem access

Erasure coding

Reed-Solomon systematic Vandermonde coding per slab, with offline repair. Lose some slabs? Reconstruct from the parity shards.

Architecture

┌─────────────────────────────────────────────────┐
│                  .lim image                     │
│  ┌───────────┐  ┌──────────┐  ┌──────────────┐ │
│  │  Manifest  │  │ Metadata │  │   Slabs      │ │
│  │ (header,   │  │ (Merkle  │  │ (compressed  │ │
│  │  flags,    │  │  B-tree  │  │  drops with  │ │
│  │  Merkle    │  │  directory│  │  BLAKE3      │ │
│  │  root)     │  │  tree)   │  │  identity)   │ │
│  └───────────┘  └──────────┘  └──────────────┘ │
└─────────────────────────────────────────────────┘

Three separately-versioned layers: drop store (content-addressed chunks), metadata (directory tree), manifest (signed root). No layer reaches into another’s bytes.

Pure Rust. Air-gapped safe.

#![forbid(unsafe_code)] workspace-wide. Zero C dependencies. The default build compiles on any machine with a Rust toolchain — no system libraries, no pkg-config, no autotools. This makes LimniFS suitable for:

  • Air-gapped environments where C toolchains aren’t available
  • Reproducible builds where every dependency must be auditable
  • Embedded systems where binary size and build simplicity matter
  • CI pipelines where cross-compilation targets lack C cross-compilers

Try it

cargo install limni
limni limn my-project/ my-project.lim
limni verify my-project.lim
limni ls my-project.lim
limni extract my-project.lim output/

Or build from source:

git clone https://github.com/limnifs/limnifs.git
cd limnifs && cargo build --release

What’s next

  • omnizip-rs integration: replacing ruzstd and lzma-rs with our own pure-Rust codec ports from omnizip/omnizip-rs. The omnizip-lzma decoder is already integrated; omnizip-zstd follows once the Huffman literals path is complete.
  • Writable images: epoch chains for content-addressed commits on top of a base .lim image. The epoch format is already implemented; replay and commit are next.
  • Dictionary compression: ZSTD dictionaries for small-file ratio.
  • Full Brotli / DEFLATE / bzip2 / PPMd ports: expanding the codec portfolio via omnizip-rs.

Acknowledgments

LimniFS builds on ideas from many projects: DwarFS (content classification), ZSTD (frame format), Git (content addressing), OSTree (Merkle trees), and 7-Zip (LZMA). The omnizip Ruby project provided the algorithmic reference for our pure-Rust codec ports.

The format specification, Python reference reader, and conformance suite live at limnifs/spec and limnifs/limnifs-py.


LimniFS v0.1.0 is available now. 495 tests. CI green. Pure Rust. Try it.