Developer Tools & Infrastructure Upstream Merged v0.2.0 2026 Dual: MIT / WaqfDPL-1.0

fs-relay

Rootless Linux FUSE filesystem over HTTP and WebSockets, ~10x faster than s3fs and fuse-nfs

FLOSS ContributionGo / FUSE v3POSIX Advisory LocksZero Root / Zero CGODual MIT / WaqfDPL
fs-relay editorial woodblock artwork
Linux & macOS
go install github.com/muayyad-alsadi/fs-relay/cmd/fs-relay@v0.2.0 && go install github.com/muayyad-alsadi/fs-relay/cmd/fs-relay-bind@v0.2.0
Domain Developer Tools & Infrastructure
Languages Go
License Dual: MIT / WaqfDPL-1.0
Status Upstream Merged
The Problem

Why This Was Built

Sharing directories across machines or coding agents via NFS, SMB, or s3fs requires root privileges or complex firewall rules, suffers from high per-file round-trip latency, and corrupts SQLite databases due to missing or local-only POSIX locks.

The Solution

The Architectural Answer

A rootless FUSE v3 mount over standard HTTP and WebSockets that batches small-file and directory prefetches, streams large files via splice pipes, and coordinates POSIX byte-range locks on the server so concurrent SQLite writers stay consistent.

Upstream Contribution Status: MERGED

Upstreamed to muayyad-alsadi/fs-relay

Muayyad Alsadi (@muayyadalsadi) created fs-relay to give Linux machines and cloud sandboxes a fast, rootless remote filesystem over plain HTTP without the per-file latency of s3fs or the fragility of NFS. He invited me to contribute to the project, where we collaborated on multi-mount SQLite POSIX locking, data-root safety, clean unmount handling, and the v0.2.0 release. Read the full background and benchmarks in Mounting Remote Disks Over Plain HTTP: Contributing to fs-relay.

Capabilities

Key Features & Architecture

Unpacks and packs archives ~10x faster than s3fs and fuse-nfs via batch reads/readdirs prefetching, 1 MiB write-behind, and raw splice sockets
Server-authoritative POSIX record locks (getlk, setlk, setlkw, flock) with dedicated SQLite pending, reserved, and shared range counters
Startup validation, non-blocking -token-file secret loading, and symlink-hardened .fs-relay.lock single-server protection
Bounded 2-second clean unmount on SIGINT/SIGTERM with interruptible fusermount3 -uz / MNT_DETACH fallback when busy
Two-phase staged self-updater (update, version, help) with SHA-256 digest verification, permission preservation, and automatic rollback
Quickstart

How-To Guide

Install fs-relay and fs-relay-bind

Install both static pure-Go binaries (server and FUSE v3 client) onto your PATH, or build them from a local clone with just build. Ensure fuse3 (fusermount3) is installed on any Linux machine that will mount a share.

Terminal
go install github.com/muayyad-alsadi/fs-relay/cmd/fs-relay@v0.2.0
go install github.com/muayyad-alsadi/fs-relay/cmd/fs-relay-bind@v0.2.0

Create a bearer token file and start the server

Write a shared secret to a mode-0600 file so the token never appears in process listings (ps aux), create the namespace directory under ./data/<namespace>/, and start fs-relay.

Terminal
umask 077 && openssl rand -hex 32 > ./token.txt
mkdir -p ./data/myproject
fs-relay -listen 127.0.0.1:8080 -data ./data -token-file ./token.txt

Mount a namespace on one or more Linux clients

Create an empty mountpoint directory and run fs-relay-bind. By default it uses a persistent WebSocket for low-latency RPCs and blocking lock wakeups; pass -post if your reverse proxy blocks WebSockets.

Terminal
mkdir -p /tmp/demo
fs-relay-bind -url http://127.0.0.1:8080 -ns myproject -token-file ./token.txt /tmp/demo

Run concurrent SQLite or DuckDB workloads across mounts

Point SQLite at the mounted directory using rollback journal mode (DELETE or TRUNCATE, which is SQLite's default). Server-side POSIX byte-range locks serialize writers across multiple mounts and flush/invalidate client caches at lock boundaries.

Terminal
sqlite3 /tmp/demo/app.db "PRAGMA journal_mode=DELETE; CREATE TABLE IF NOT EXISTS runs (id INTEGER PRIMARY KEY, host TEXT); INSERT INTO runs (host) VALUES (hex(randomblob(4))); SELECT * FROM runs;"

Unmount cleanly or self-update in place

Press Ctrl+C (SIGINT) or send SIGTERM to fs-relay-bind: it attempts a clean unmount within 2 seconds and falls back to a lazy detach (fusermount3 -uz) if a process still holds an open file. To upgrade both binaries in place with SHA-256 verification and automatic rollback, run fs-relay update.

Terminal
fusermount3 -u /tmp/demo
fs-relay update
Engineering

Technical Specifications

Primary Languages
Go
Frameworks & Tooling
go-fuseGoogle FlatBuffers
Architecture & Execution Model
5-package pure Go design (CGO_ENABLED=0): FUSE v3 client with batch small-file/dir prefetching and 1 MiB write-behind, FlatBuffers over HTTP/WebSockets, raw splice socket, and server-side POSIX lock table
Licensing Model
Dual: MIT / WaqfDPL-1.0 (permissive)
Release & Lineage
Active release cycle since 2026 · Maintained by @JadMadi
Knowledge

Frequently Asked Questions

Why use fs-relay instead of NFS, SSHFS, or s3fs?

Muayyad Alsadi (@muayyadalsadi) designed fs-relay so remote folders mount over standard HTTP and WebSockets without root, VPNs, or kernel modules, while batching small-file and directory prefetches to run ~10x faster than s3fs and fuse-nfs on source-tree workloads.

Does fs-relay support concurrent SQLite access across mounts?

Yes, in rollback journal mode (DELETE or TRUNCATE). The server coordinates POSIX byte-range locks across mounts, and fs-relay-bind drains buffered writes before unlocking and invalidates cached bytes on lock grant. WAL mode is not supported because it requires shared memory (mmap) across hosts.

Do I need root access or kernel modules to run it?

No. Both fs-relay and fs-relay-bind are pure Go static binaries (CGO_ENABLED=0) that run as an unprivileged user on Linux with FUSE v3 (fusermount3).