- Zig 100%
| .forgejo/workflows | ||
| docs | ||
| src/nexfs | ||
| tests | ||
| .gitignore | ||
| .grafignore | ||
| build.zig | ||
| build.zig.zon | ||
| LICENSE | ||
| NEXFS-DEVELOPMENT-PLAN.md | ||
| NEXFS-STORAGE-STACK-OVERVIEW.md | ||
| nexfs_size_check | ||
| README.md | ||
| test_zig | ||
NexFS — The Sovereign Flash Filesystem
Flash-native. Content-addressed. The BitTorrent killer built into your filesystem.
Why NexFS Exists
Every filesystem you have used was designed for spinning rust, POSIX, and single machines. NexFS was designed for flash, sovereignty, and mesh networks.
Three profiles. One format. Zero POSIX baggage.
| Profile | What It Does | Footprint | Target |
|---|---|---|---|
| nexfs-core | Power-safe flash storage with hash-verified metadata | ~40KB | IoT, Satellite, Sensor, MCU |
| nexfs-sovereign | + Content-defined chunking, Merkle DAG, dedup, time travel | ~120KB | Phone, Laptop, Desktop |
| nexfs-mesh | + UTCP cluster, gossip, chapter mesh, kinetic credits | ~200KB | Home Box, Chapter Node, Ground Station |
An IoT sensor runs nexfs-core and never loads a byte of network code. A laptop runs nexfs-sovereign with full dedup and snapshots. A home box runs nexfs-mesh and becomes a node in the Chapter Network. Same filesystem format; different cognitive capacity.
The BitTorrent Killer
This is not a metaphor.
When nip install firefox runs on a Sovereign device, NexFS does not download a tarball from a central server. It resolves the package to a list of CAS chunk CIDs (BLAKE3 hashes), checks which chunks it already has locally, and requests the missing ones from Chapter Mesh peers over UTCP. If no peer has the chunk, it falls back to the Seed server.
The result: popular packages propagate through the mesh like a self-healing swarm. The Seed server serves each chunk once to the first node. After that, the mesh takes over.
Why This Beats BitTorrent
| BitTorrent | NexFS Chapter Mesh | |
|---|---|---|
| Integration | Separate torrent client | Native filesystem; nip install just works |
| Delta Updates | Re-download entire file | CAS dedup; Firefox 120→121 transfers ~5% delta |
| Encryption | Optional, bolt-on | Encrypted at rest by default (Monolith key) |
| NAT Traversal | Tracker/DHT, NAT-punching hell | UTCP CellID routing; no NAT problem |
| Discovery | Central tracker or DHT | Gossip-based peer discovery |
| Economy | Goodwill (leechers win) | Kinetic Credits; contribute more, get more |
| Dedup | Per-file | Per-chunk across all files, all nodes |
Concrete example: Firefox 120.0.1 and 120.0.2 share 95% of their content-defined chunks. BitTorrent transfers the whole archive again. NexFS transfers 5%.
The Chapter Pool
Every Sovereign home installation dedicates a partition to the Chapter Network:
┌─ /dev/nvme0 ──────────────────────────────────┐
│ │
│ Partition 1: nexfs-sovereign (Root, Private) │
│ ├── /Cas (System, Immutable) │
│ ├── /Nexus (Config, Encrypted) │
│ └── /Data (User, Encrypted) │
│ │
│ Partition 2: nexfs-mesh (Chapter Pool) │
│ ├── Encrypted at rest (Monolith) │
│ ├── Auto-joins Chapter via UTCP Discovery │
│ ├── Contributes: Storage + Bandwidth │
│ └── Receives: Redundancy + Content Access │
│ │
└────────────────────────────────────────────────┘
# During Sovereign installation
nexus forge --chapter "frankfurt-01"
# User sees:
# "How much storage do you want to contribute to the Chapter Network?"
# [Slider: 10GB ... 500GB ... 2TB]
# Default: 10% of disk or 50GB, whichever is smaller
nexfs format /dev/nvme0p2 --mode sovereign-mesh \
--chapter-id "frankfurt-01" \
--quota 50G \
--replication-factor 3
The node operator cannot inspect transit chunks stored on their disk. Sealed with Monolith-derived keys. Plausible deniability by architecture.
Kinetic Credits (SPEC-053)
No altruism. No charity. Engineered reciprocity.
| Action | Credits |
|---|---|
| Store 1GB for mesh (per day) | +10 |
| Serve 1GB to mesh peers | +5 |
| Download 1GB from mesh | -2 |
| Download 1GB from Seed (bypass mesh) | -10 (penalty) |
| 99.9% uptime (monthly) | +100 bonus |
Commonwealth packages are always free. Premium content and priority bandwidth cost credits.
Hash Configuration
NexFS supports configurable hash algorithms per volume. The hash algorithm is stored in the Superblock and determines integrity verification for all metadata and CAS operations.
nexfs format --hash blake3-256 # Default. Cryptographic. Future-proof.
nexfs format --hash blake3-128 # Compact sovereign. Same algorithm, truncated output.
nexfs format --hash xxh3-64 --force # Ultra-constrained only. Birthday collision at ~2³².
The --force flag on XXH3-64 is not paternalism; it is an audit trail. When someone asks in three years why checksums collided, the format log shows it was a conscious decision.
Hash Decision Matrix
| Hash ID | Algorithm | Output | Use Case |
|---|---|---|---|
0x00 |
BLAKE3 | 256-bit | Default. CAS, Merkle DAG, ProvChain. |
0x01 |
BLAKE3 | 128-bit | Satellite with crypto requirements, tighter block pointers. |
0x02 |
XXH3 | 64-bit ⚠️ | MCU with extreme constraints. Requires --force. |
BLAKE3 is an XOF (Extendable Output Function); 128-bit and 256-bit use the same algorithm with different output truncation.
Rule of thumb: 128-bit minimum for anything that lives longer than a reboot.
Architecture
On-Disk Layout
┌─────────────────────────────────────────────┐
│ Block 0: Primary Superblock (128 bytes) │
├─────────────────────────────────────────────┤
│ Block 1: Backup Superblock (128 bytes) │
├─────────────────────────────────────────────┤
│ Blocks 2-N: Block Allocation Map (BAM) │
│ - Allocation status per block │
│ - Erase counts (wear leveling) │
│ - Bad block marking │
├─────────────────────────────────────────────┤
│ Blocks N+1-N+4: Inode Table │
│ - File/directory metadata │
│ - Inode IDs 1-128 │
├─────────────────────────────────────────────┤
│ Blocks N+5+: Data Blocks │
│ - File/directory contents │
│ - Wear-leveled allocation │
└─────────────────────────────────────────────┘
Superblock
const Superblock = struct {
magic: u32, // 0x4E455846 ("NEXF")
version: u16, // Format version
hash_algo: u8, // 0x00=BLAKE3-256, 0x01=BLAKE3-128, 0x02=XXH3-64
profile: u8, // 0x00=core, 0x01=sovereign, 0x02=mesh
generation: u64, // Monotonic; crash recovery
mount_count: u32, // Health monitoring
block_size: u32,
block_count: u32,
chapter_id: [16]u8, // 128-bit CellID (mesh only; zero otherwise)
mesh_quota: u64, // Bytes for mesh (mesh only; zero otherwise)
replication_target: u8, // Desired copies (default 3)
checksum: [32]u8, // Self-checksum (algorithm per hash_algo)
};
Flash Interface
Zero allocation. All buffers provided by caller.
pub const FlashInterface = struct {
read: *const fn (ctx: *anyopaque, addr: u64, buffer: []u8) NexFSError!usize,
write: *const fn (ctx: *anyopaque, addr: u64, buffer: []const u8) NexFSError!void,
erase: *const fn (ctx: *anyopaque, block_addr: BlockAddr) NexFSError!void,
sync: *const fn (ctx: *anyopaque) NexFSError!void,
};
Key Components
Block Allocation Map (BAM): Per-block metadata tracking allocation status, erase counts for wear leveling, and bad block flags. Generation counter for block age.
Inode Table: File and directory metadata. Supports Regular, Directory, Symlink, and Device node types. Max filename: 255 characters (UTF-8).
Dual Superblock: Primary + backup. If one corrupts, the other survives. No journal to replay; metadata writes are atomic at the block level.
Build System
Core Layer (Zig)
NexFS Core is pure Zig with zero dependencies. Build profiles are controlled via comptime flags:
// nexfs/config.zig
pub const Profile = enum {
core, // Block Valve + Hash verification only
sovereign, // + CAS, CDC, Merkle DAG, TimeWarp
mesh, // + UTCP Storage, Gossip, Replication
};
pub const build_profile: Profile = if (@hasDecl(root, "nexfs_profile"))
root.nexfs_profile
else
.core; // Default: minimal
pub const has_cdc = build_profile == .sovereign or build_profile == .mesh;
pub const has_dag = build_profile == .sovereign or build_profile == .mesh;
pub const has_mesh = build_profile == .mesh;
# Build core (IoT, satellite)
zig build -Dnexfs_profile=core
# Build sovereign (laptop, phone)
zig build -Dnexfs_profile=sovereign
# Build mesh (chapter node, home box)
zig build -Dnexfs_profile=mesh
Sovereign & Mesh Layers (Nim)
The Sovereign extensions (SPEC-085) and Mesh protocol (SPEC-704) run in the Membrane (userland) as NPL services, written in Nim. They consume NexFS Core via the Block Valve (SPEC-083).
# libs/membrane/nexfs/sovereign/config.nim
const
nexfs_cdc* = defined(nexfs_cdc) # Content-Defined Chunking
nexfs_dag* = defined(nexfs_dag) # Merkle DAG Directories
nexfs_dedup* = defined(nexfs_dedup) # Local Deduplication
nexfs_timewarp* = defined(nexfs_timewarp) # Snapshot Time Travel
nexfs_mesh* = defined(nexfs_mesh) # UTCP Cluster + Gossip
# Sovereign membrane module
nim c -d:nexfs_cdc -d:nexfs_dag -d:nexfs_dedup -d:nexfs_timewarp nexfs_sovereign.nim
# Mesh membrane module (includes sovereign)
nim c -d:nexfs_cdc -d:nexfs_dag -d:nexfs_dedup -d:nexfs_timewarp -d:nexfs_mesh nexfs_mesh.nim
The split is architectural, not accidental:
- Zig handles the physics: raw flash I/O, sector checksums, wear leveling, zero-allocation constraints. Kernel-adjacent; runs in the Block Valve.
- Nim handles the logic: CAS indexing, CDC chunking, Merkle DAG operations, UTCP gossip, replication policy. Userland; runs in the Membrane.
A crash in the Nim Membrane layer does not take down the kernel. The Block Valve keeps serving raw sectors. The Membrane restarts clean. This is the Blink recovery pattern (SPEC-021).
Sovereign Extensions (SPEC-085)
Content-Defined Chunking (FastCDC)
Traditional filesystems split files by fixed offset. Insert one byte at the start of a 1GB file and every block shifts. Dedup dies. Sync re-transfers everything.
NexFS splits by content boundaries using a Gear-hash rolling window:
| Parameter | Default | Configurable |
|---|---|---|
| Min chunk | 16 KB | Per-volume in Superblock |
| Avg chunk | 64 KB | Per-volume in Superblock |
| Max chunk | 256 KB | Per-volume in Superblock |
Identical byte sequences across different files produce identical chunks automatically. VM images sharing a base OS: ~90% dedup. Source repos with branches: ~95%. Software updates: ~95%.
Content-Addressable Storage (CAS)
Every chunk is stored exactly once, addressed by its BLAKE3 hash. Dedup is inline at write time; no background processing, no dedup tables eating RAM.
$ nexfs status /Data
NexFS Sovereign Volume: /Data
Logical Size: 847.3 GB
Physical Size: 612.1 GB
Dedup Ratio: 1.38x
Chunks: 9,847,221
Unique Chunks: 7,104,887
Hash Algorithm: BLAKE3-256
Merkle DAG (The Inode Killer)
POSIX inodes are mutable, numbered, tied to a single filesystem, and impossible to verify. NexFS replaces them with a Merkle DAG: every file is a list of chunk CIDs, every directory is a cryptographic commitment to its children.
Updating a file creates new versions of ancestor nodes up to the root. The unchanged chunks remain shared via CAS refcounting. Cost of an update: one new chunk + O(depth) new DAG nodes.
The DAG root is the only mutable structure in the Sovereign layer. Everything it points to is immutable.
TimeWarp (Snapshots)
Snapshots cost zero additional storage; a snapshot is a 128-byte DAG node pointing to an existing root. Storage grows only when data changes after the snapshot.
# Create
$ nexfs snap create "before-upgrade"
# List
$ nexfs snap list
2026-02-16 14:30 before-upgrade blake3:d4e2...
2026-02-15 03:00 daily-2026-02-15 blake3:a1b2...
# Browse (read-only mount)
$ nexfs snap mount "before-upgrade" /Data/Volume/Local/timewarp
# Rollback (atomic; one Root Register swap)
$ nexfs snap rollback "before-upgrade"
# Diff
$ nexfs snap diff "daily-2026-02-14" "daily-2026-02-15"
+ /Data/User/markus/Documents/contract-final.pdf (247 KB, 4 chunks)
~ /Data/User/markus/.config/nexshell.kdl (2 chunks changed)
- /Data/Cache/nip/build-artifacts/stale.o (removed)
Automatic snapshots via KDL config:
nexfs {
timewarp {
auto-snap-interval "6h"
retention-daily 7
retention-weekly 4
retention-monthly 12
gc-orphan-delay "24h"
}
}
UTCP Storage Protocol (SPEC-704)
The wire protocol for distributed block exchange between Mesh nodes. 16-byte extension header on existing UTCP frames (SPEC-093).
Operations
| Category | Ops | Purpose |
|---|---|---|
| Block | HAVE, WANT, PUT, DROP, DENY | Chunk exchange and announcements |
| DAG | SYNC, DIFF, WANT_TREE | Merkle root comparison and tree sync |
| Peer | ANNOUNCE, HEARTBEAT, LEAVING | Discovery, health, graceful departure |
Flow
Node A Node B
│ │
├──BLOCK_WANT(cid:a7f2...)────►│
│ ├── CAS lookup + verify
│◄──BLOCK_PUT(cid:a7f2...)─────┤
├── BLAKE3 verify │
├── CAS store │
Latency target: < 200µs on LAN. Credit-based flow control prevents fast nodes from overwhelming slow ones.
Security
Every BLOCK_PUT is hash-verified by the receiver. A malicious node that sends garbage fails immediately; BLAKE3 does not lie. Peers authenticate via Ed25519 CellID signatures (SPEC-051). Poisoning is architecturally impossible: the CID is the hash. You cannot forge a valid CID for garbage data without breaking BLAKE3.
Quick Start
Installation
Add NexFS to your build.zig.zon:
.{
.name = "your-project",
.version = "0.1.0",
.dependencies = .{
.nexfs = .{
.url = "https://git.sovereign-society.org/nexus/nexfs/archive/main.tar.gz",
.hash = "...",
},
},
}
Basic Usage
const std = @import("std");
const nexfs = @import("nexfs");
pub fn main() !void {
// 1. Provide your flash HAL
var flash = MyFlash{ .flash_data = try allocator.alloc(u8, 1024 * 1024) };
// 2. Provide buffers (zero dynamic allocation)
var read_buf: [4096]u8 = undefined;
var write_buf: [4096]u8 = undefined;
var workspace: [256]u8 = undefined;
const config = nexfs.Config{
.flash = .{
.ctx = &flash,
.read = MyFlash.read,
.write = MyFlash.write,
.erase = MyFlash.erase,
.sync = MyFlash.sync,
},
.device_size = 1024 * 1024,
.block_size = 4096,
.block_count = 256,
.page_size = 256,
.hash_algo = .blake3_256, // Configurable per volume
.read_buffer = &read_buf,
.write_buffer = &write_buf,
.workspace = &workspace,
.time_source = null,
.verbose = true,
};
// 3. Format
try nexfs.format(&config.flash, &config, &write_buf);
// 4. Write
var fs = try nexfs.NexFS.init(allocator, config);
const fd = try fs.create("/config.txt");
try fs.write(fd, "hello nexfs");
try fs.close(fd);
// 5. Read
var buf: [64]u8 = undefined;
const fd2 = try fs.open("/config.txt");
const len = try fs.read(fd2, &buf);
try std.io.getStdOut().writeAll(buf[0..len]);
try fs.close(fd2);
}
Recommended Configurations
Raspberry Pi + SPI Flash (1MB):
.block_size = 4096, .page_size = 256, .block_count = 256,
.hash_algo = .blake3_128, // Crypto integrity, compact pointers
ESP32 + Flash (4MB):
.block_size = 4096, .page_size = 256, .block_count = 1024,
.hash_algo = .xxh3_128, // Speed priority, local trust
Microcontroller + NOR Flash (512KB):
.block_size = 2048, .page_size = 256, .block_count = 256,
.hash_algo = .xxh3_128, // Minimal overhead
Use Cases
Libertaria Mesh Nodes
Primary use case. NexFS provides the persistence layer for SoulKeys, peer tables, trust graphs, and message queues.
┌─────────────────────────────────────────┐
│ Libertaria Capsule Node │
├─────────────────────────────────────────┤
│ L3 Gossip (QVL Trust Edges) │
│ L2 Session (Noise Handshakes) │
│ L1 Identity (SoulKeys) │
│ NexFS (Persistent Storage) ◄───┤
│ Raw Flash (NAND/NOR/SPI) │
└─────────────────────────────────────────┘
Embedded Sovereign Devices
Solar monitors, weather networks, pager devices, home automation. Anywhere you need persistence on raw flash without an FTL, an OS, or an allocator.
Sovereign Desktops and Laptops
Full dedup, Merkle DAG directories, TimeWarp snapshots. Replaces EXT4/Btrfs/APFS with a filesystem designed for content-addressing from day one.
Chapter Network Nodes
Home boxes that contribute storage to the decentralized mesh. Package distribution, content sharing, redundancy; all native to the filesystem.
Design Philosophy
Five Principles
- No Secrets. All code is open source and auditable (LSL-1.0).
- No Dependencies. Zero external libraries in Core. Pure Zig.
- No Vendor Lock-in. Standard flash interface. Portable anywhere.
- No Hidden Allocation. Explicit memory management. Caller provides all buffers.
- No Trust Required. Every metadata structure is hash-verified. Every chunk is content-addressed.
Flash-Aware Design
Raw flash, not FTL. Predictable performance without FTL latency spikes. Full control over wear leveling. No consumer-grade write amplification. No background garbage collection burning your battery.
Wear Leveling Strategy: Track erase counts per block in the BAM. Prefer lowest-count blocks for writes. Reserve high-count blocks for cold data. Target: even distribution across flash lifetime.
Performance
| Operation | Typical Latency | Notes |
|---|---|---|
| Mount | < 10ms | Read superblock, validate hash |
| Format | 100-500ms | Initialize all metadata blocks |
| File Create | 5-20ms | Allocate inode, write metadata |
| File Read (4KB) | 1-5ms | Single block read + hash verify |
| File Write (4KB) | 10-30ms | Erase + write cycle |
| CDC Chunking | > 2 GB/s | FastCDC with SIMD gear-hash (sovereign) |
| CAS Put (dedup hit) | < 5µs | Hash lookup + refcount increment (sovereign) |
| Snapshot Create | < 10µs | One DAG node + Root Register swap (sovereign) |
| BLOCK_WANT→PUT | < 200µs | LAN round-trip (mesh) |
Memory: Minimum 2 × block_size + page_size (~8.5KB for 4KB blocks). No allocator required.
Testing
Current: 51/51 tests passing (100%)
zig build test # Run all tests
zig build test -Dverbose # Verbose output
Coverage: Superblock validation, hash algorithms (BLAKE3-256, BLAKE3-128, XXH3-64), block allocation/deallocation, inode CRUD, directory operations (create/delete/lookup/iterate), file I/O (read/write/seek), path resolution, format round-trip, createFile/createDir, deleteFile/deleteDir, error conditions.
Specifications
NexFS is defined by three SPECs that build on each other:
| SPEC | Name | Scope |
|---|---|---|
| SPEC-084 | NexFS Core Format | Superblock, block pointers, hash-ID, profile byte. The foundation. |
| SPEC-085 | NexFS Sovereign Extensions | FastCDC, CAS, Merkle DAG, local dedup, TimeWarp. The mind. |
| SPEC-704 | UTCP Storage Extensions | Wire protocol for mesh block exchange, gossip, replication. The network. |
SPEC-084 (Core) ──► SPEC-085 (Sovereign) ──► SPEC-704 (Mesh)
│ │ │
~40KB +80KB +80KB
IoT Laptop Home Box
Each SPEC is independently implementable. core compiles without the others.
Roadmap
v0.2.0 (Q2 2026) — Sovereign Profile
SPEC-085 implementation: FastCDC chunker, CAS store with inline dedup, Merkle DAG directory structure, TimeWarp snapshots, active wear leveling, bad block management, hash algorithm selection.
v0.3.0 (Q3 2026) — Mesh Profile
SPEC-704 implementation: UTCP storage protocol, gossip-based peer discovery, cross-node dedup, Chapter Mesh integration, Kinetic Credits, credit-based flow control, LZ4 compression, nexfs fsck.
v1.0.0 (Q4 2026) — Production
XChaCha20-Poly1305 encryption, CRDT for concurrent DAG edits, multi-chapter federation, production hardening, full Libertaria stack integration.
Security
Data Integrity: Configurable hash algorithm (BLAKE3-256 default) protects all metadata. Dual superblock survives single-block corruption. CAS verification on every read; silent corruption is impossible.
Power-Loss Resilience: Primary + backup superblock. Atomic metadata writes. No journal to replay. Sovereign layer: immutable DAG with single mutable Root Register; odd generation = incomplete write = automatic rollback.
Mesh Security: Every chunk is hash-verified on receipt. Peer authentication via Ed25519 CellID signatures. Transit chunks encrypted at rest with Monolith-derived keys. Poisoning is architecturally impossible.
Planned: XChaCha20-Poly1305 encryption at rest, AEAD, SoulKey-derived key integration.
Contributing
Status: Alpha (v0.3.0)
Areas: Wear leveling algorithm, bad block detection, performance optimization, test coverage, documentation.
Code Style: Zig style guidelines. SPDX license headers required. BDD-style tests preferred. Panopticum architecture compliance.
License
LSL-1.0 (Libertaria Sovereign License 1.0)
Open source. Auditable. Free for sovereign applications. Modifications must be contributed back. No commercial restrictions for sovereign use.
See LICENSE for full text.
Community
Repository: git.sovereign-society.org/nexus/nexfs
Nexus Ecosystem: rumpk · nip · nipbox · nexfs
Related: Libertaria Stack · Janus Language
Inspired by: LittleFS (flash resilience), JFFS2 (journaling flash), IPFS (content addressing). Built to surpass all three.
"The past is not deleted. It is addressed."