A pure Rust implementation of the CernVM-FS client. Mount remote CVMFS repositories as local filesystems via FUSE, with full content verification and transparent decompression.
The original CernVM-FS client is written in C++. This project rewrites the client in Rust to get:
- Memory safety without garbage collection
- Fearless concurrency for multi-threaded FUSE operations
- Modern tooling: cargo, clippy, built-in testing, dependency management
- Smaller binary: single static binary, no shared library dependencies beyond FUSE
- Multi-threaded FUSE filesystem via
fuserwithreaddirplus(Linux) - Transparent decompression (zlib, LZ4, Zstd) of content-addressed objects
- RSA-PKCS1v15 signature verification of repository manifests
- Whitelist validation (repository name matching + expiry checks)
- SQLite catalog traversal with nested catalog support
- Multiple hash algorithms: SHA-1, RIPEMD-160, SHA-256, SHAKE-128
- Full directory entry metadata: uid/gid, hardlinks, xattr, special file types
- Chunked file reassembly for large files
- External data file support (content stored outside CAS)
- Local object caching with TTL-based invalidation and negative caching
- Reflog support for tracking historical root catalog hashes
- HTTP/HTTPS retrieval from Stratum-1 replica servers
- Mirror failover with automatic retry across multiple sources
- Geolocation-based server selection via CVMFS geo API
- DNS-based repository server discovery via TXT records
cargo binstall cvmfsPre-built binaries available for:
x86_64-unknown-linux-gnuaarch64-unknown-linux-gnux86_64-apple-darwinaarch64-apple-darwin
cargo install cvmfs- FUSE 3 libraries:
- macOS: macFUSE (
brew install --cask macfuse) - Linux:
sudo apt install libfuse3-dev(Debian/Ubuntu) orsudo dnf install fuse3-devel(Fedora)
- macOS: macFUSE (
git clone https://github.com/moliholy/cvmfs-rust.git
cd cvmfs-rust
cargo build --releasemkdir -p /tmp/cvmfs_mount
./target/release/cvmfs-cli http://cvmfs-stratum-one.cern.ch/opt/boss /tmp/cvmfs_mountThen browse /tmp/cvmfs_mount like any local directory. Unmount with:
# macOS
umount /tmp/cvmfs_mount
# Linux
fusermount -u /tmp/cvmfs_mountcvmfs-cli <repository_url> <mount_point> [cache_directory]
| Argument | Required | Default | Description |
|---|---|---|---|
repository_url |
Yes | URL of the CernVM-FS repository | |
mount_point |
Yes | Local directory to mount | |
cache_directory |
No | /tmp/cvmfs |
Directory for cached objects |
RUST_LOG=info cvmfs-cli http://cvmfs-stratum-one.cern.ch/opt/boss /tmp/cvmfs_mountcvmfs-rust exposes a library crate for programmatic access:
use cvmfs::{fetcher::Fetcher, repository::Repository};
let fetcher = Fetcher::new("http://cvmfs-stratum-one.cern.ch/opt/boss", "/tmp/cache", true) ?;
let mut repo = Repository::new(fetcher) ?;
// List root directory
for entry in repo.list_directory("/") ? {
println ! ("{} ({})", entry.name, if entry.is_directory() { "dir" } else { "file" });
}
// Read a file
let mut file = repo.get_file("/testfile") ?;
let mut contents = String::new();
file.read_to_string( & mut contents) ?;use cvmfs::fetcher::Fetcher;
let fetcher = Fetcher::with_mirrors(
& ["http://primary.cern.ch/opt/boss", "http://mirror1.cern.ch/opt/boss"],
"/tmp/cache",
true,
) ?;use cvmfs::dns::discover_servers;
let servers = discover_servers("boss.cern.ch") ?;Both implementations mounted via FUSE on Linux (Docker), benchmarked
with hyperfine
(100 runs, 10 warmup). C++ cvmfs2 v2.13.3. Repository: boss.cern.ch. Multi-threaded fuser with readdirplus.
Rust dominates bulk I/O. Metadata operations at parity (sub-ms, within measurement noise).
| Operation | Rust | C++ | Ratio |
|---|---|---|---|
| stat / (root) | 0.4ms | 0.4ms | ~1.0x |
| stat /testfile | 0.3ms | 0.3ms | ~1.0x |
| stat /database | 0.3ms | 0.3ms | ~1.0x |
| stat symlink | 0.4ms | 0.4ms | ~1.0x |
| readlink symlink | 0.2ms | 0.2ms | ~1.0x |
| Operation | Rust | C++ | Ratio |
|---|---|---|---|
| ls / (root) | 0.4ms | 0.4ms | ~1.0x |
| ls /database | 0.4ms | 0.4ms | ~1.0x |
| ls /pacman-3.29 | 0.5ms | 0.4ms | ~1.0x |
| ls /slc4_ia32_gcc34 (nested) | 0.5ms | 0.4ms | ~1.0x |
| Operation | Rust | C++ | Winner |
|---|---|---|---|
| cat /testfile (50B) | 0.3ms | 0.3ms | ~1.0x |
| head -c 16 offlinedb.db (chunked) | 0.4ms | 0.4ms | ~1.0x |
| head -c 2 pacman-latest.tar.gz | 0.3ms | 0.3ms | ~1.0x |
| dd seek+read offlinedb.db | 0.4ms | 0.4ms | ~1.0x |
| cat pacman-latest.tar.gz (full) | 0.3ms | 0.3ms | ~1.0x |
| wc -c /testfile | 0.3ms | 0.3ms | ~1.0x |
| Operation | Rust | C++ | Ratio |
|---|---|---|---|
| find /pacman-3.29 -maxdepth 1 | 0.5ms | 0.5ms | ~1.0x |
| find /database -type f | 0.5ms | 0.5ms | ~1.0x |
| find / -maxdepth 3 | 5.7ms | 4.9ms | C++ +14% |
| du -d 2 | 0.2ms | 0.2ms | ~1.0x |
| Operation | Rust | C++ | Winner |
|---|---|---|---|
| md5 run.db (chunked, 410MB) | 759ms | 789ms | Rust +4% |
| cat run.db (chunked, 410MB) | 40ms | 48ms | Rust +21% |
| md5 /testfile | 0.3ms | 0.3ms | ~1.0x |
| md5 pacman-latest.tar.gz | 1.9ms | 1.9ms | ~1.0x |
make bench # run locally (requires sudo, cvmfs2, hyperfine)
make bench-docker # run in Docker (recommended, Linux FUSE with n_threads)make test # run all tests (uses cargo-nextest)
make lint # clippy with -D warnings
make fmt # format with nightly rustfmt
make coverage # generate coverage report
make bench # benchmark Rust vs C++ cvmfs2 (requires sudo)
make bench-docker # benchmark in Docker (recommended)See CHANGELOG.md for release history.
BSD 3-Clause. See LICENSE.
- cvmfs-java: Java port of the CernVM-FS client