xhfs 0.5.0

Bruteforce your way into storing files anywhere across an arbitrary combination of arbitrary devices.
# XHFS (Extended Headless File System)


XHFS is a small, full-fledged file system that enables you to store files
anywhere, on anything, across an arbitrary combination of arbitrary devices.

# Concept


Fundamentally, any writable, readable, and seekable abstract block device can be
used as a storage device, whether or not it was built for such an operation: be
it a file on disk, a remote Key-Value store (Redis, Cloudflare KV), or heck,
even a database.

XHFS makes no assumptions about what the underlying "device" actually is; in
fact, it remains entirely agnostic as long as you provide a way to read/write to
arbitrary locations.

While its core design is inspired by ext4, the primary architectural split is
that its inode extents are organized as a linked list instead of a H Tree, which
you may argue makes it slower for seek operations but still good enough.

# Use-cases


- Basic: You can setup blob file replicas across drives on top of your local
  filesystem.
- As a storage layer on top of an existing one:
  - Split your XHFS storage into multiple files, then store them on a locally
    synchronized folder using
    [null.fs]https://github.com/michael-0acf4/null.fs, Syncthing, Google
    Drive, Mega, OneDrive or anything similar. You get an encrypted storage
    layer that can be shared publicly + automatic backups.
- Distributed: Out of the box, XHFS makes no assumptions about the underlying
  device as long as we can read/write/seek arbitrary data.
- As Yet Another Filesystem: The wiring is already there, you can hack your way
  into formatting a physical block device or write a driver for it.

# Example


Consider the following configuration:

```yaml
# xhfs.yaml

# Encrypt the drive

# or use the cli with --password helloworld if the config and bins are made public

password: helloworld
key_derivation:
  algorithm: argon2 # or sha256
devices:
  - type: file
    name: blob1
    path: ./part1.bin
  - type: file
    name: blob2
    path: ./part1-replica.bin
  - type: file
    name: blob3
    path: ./part2.bin
configuration:
  logical:
    - name: dev1
      # The data will be replicated accross these block devices.
      # The first block device will be the main block for reads
      # and we can swap the order if we suspect corruption
      include: [blob1, blob2]
      capacity: "50 MiB"
      max_concurrent: 2
    - name: dev2
      include: [blob3]
      capacity: "50 MiB"
      max_concurrent: 1
  # Final storage layout
  # [dev1: 0 - 50MB] [dev2: 50MiB - 100MiB]
  layout: [dev1, dev2]
```

All that is left to do is format the drive (if you haven't done so yet) and then
start playing with it.

```bash
# Setup the File System if not formatted yet
xhfs format

echo "Hello World" > thething.txt
xhfs upload thething.txt /test.txt

xhfs x ls -v
# FILE     2026-06-07 12:58:47  2026-06-07 12:58:33        28 B test.txt

xhfs read test.txt | echo
# Hello World

# You can also import stored files like this..
xhfs download test.txt my_physical_copy.txt
```

# Installation


Download the binary from the
[releases](https://github.com/futureg-lab/xhfs/releases) or install using cargo.

```bash
cargo install xhfs
```

## Environment variables


| Environment variable   | Equivalent config / CLI           | Default               |
| ---------------------- | --------------------------------- | --------------------- |
| `XHFS_CONFIG`          | `--config <CONFIG>`               | `xhfs.yaml`           |
| `XHFS_PASSWORD`        | config `password` or `--password` | unset (no encryption) |
| `XHFS_WEBDAV_USERNAME` | config `servers.webdav.username`  | unset (no auth)       |
| `XHFS_WEBDAV_PASSWORD` | config `servers.webdav.password`  | unset (no auth)       |

```yaml
# xhfs.yaml

password: helloworld # XHFS_PASSWORD
servers:
  webdav: # XHFS_WEBDAV_USERNAME + XHFS_WEBDAV_PASSWORD
    username: admin
    password: password
```

- Environment variables take precedence over the values in the config file.
- XHFS will automatically load from `.env` if detected.

# Features


- [x] File System
  - [x] Encryption (ChaCha20 stream cipher + argon2 or sha256 key derivation)
  - [x] No journaling, CoW based
  - [x] xhfs core: fopen, fwrite, fseek, mkdir, fmove, fcopy, unlink
  - [x] Native Symlink support: create_symlink
  - [x] Native Hardlink support: create_hardlink
  - [x] Extra: fappend
- [ ] RAID-like configuration
  - [x] Logical grouping
  - [x] Replication
  - [ ] Error correction
- [ ] No device assumption
  - [x] File device
  - [x] In memory device
  - [x] Custom KV http endpoint
  - [x] Cloudflare KV example
  - [ ] s3 device
- [x] Explorer
  - [x] CLI
  - [x] Inspection utilities: `xhfs inspect`
  - [x] Servers
    - [x] Webdav server: `xhfs server webdav`

# Inspection tools


The command line provides a few sets of utilities you can use to inspect the
formatted filesystem.

## General state


```bash
xhfs info
```

The `info` command will show you the general layout of what constitutes your
storage, this includes the remaining usable space and metadata layout.

```
Config loaded: xhfs.yaml
XHFS version: 1
Capacity:        104857600 B (100.0 MiB)
Remaining:        83886080 B (80.0 MiB)
Format Configuration:
  Block Size:            4096 B (4.0 KiB)
  Data Blocks per Group: 20480
  INode count per Group: 4096
  Total Groups:     1
Geometry Layout (relative):
  Group Stride:        84221025
  INodes per Group:    4096
  Usable Blocks/Group: 20480
  Header Region:       0x00000000 -- 0x00000050 (        81 B) (        81 B)
  Data Bitmap Region:  0x00000051 -- 0x00000a58 (      2568 B) (     2.5 KiB)
  INode Bitmap Region: 0x00000a59 -- 0x00000c60 (       520 B) (       520 B)
  INode Table Region:  0x00000c61 -- 0x00051c60 (    331776 B) (   324.0 KiB)
  Data Payload Region: 0x00051c61 -- 0x05051c60 (  83886080 B) (    80.0 MiB)
```

## INode metadata


```bash
# Display metadata of an INode and its extent address

xhfs inspect inode /Pictures/cat.jpg
# INode #4

# - Number of Links: 1

# - Kind: File

# - Size: 1050318 B

# - Creation time: 2026-05-17 21:26:29 UTC

# - Modification time: 2026-05-17 21:26:29 UTC

# - Immediate Extent address: 404025 (0x00062a39)


# then the Extent chain up to a count

xhfs inspect extent 0x00062a39 -m 3 
# #1 :: 0x00062a39 -- 0x00062e39 (      1025 B)

# #2 :: 0x00164239 -- 0x00264639 (   1049601 B)

# #3 :: 0x00264639 -- 0x00264e39 (      2049 B)

```

## Block view and dump


If you want to read from the filesystem directly, you can dump or view its
content either raw or decrypted. This can be useful if you want to make custom a
tool that reconstruct removed file extents, dump the entire filesystem content
locally or inspect the state of the data.

```bash
# which you can view in hex (don't forget to decrypt for the data and INode regions)

xhfs inspect view 0x00062a39 0x00062a50 -c 16 --decrypt
# 00000000: 00 00 00 00 00 00 00 00 39 42 16 00 00 00 00 00 | ........9B......

# 00000010: 01 00 00 00 00 00 00                            | .......


# or even dump

xhfs inspect dump 0x00062a39 0x00062a50 stuff.bin --decrypt

# and many other things too...

```

## Benchmarks


```bash
cargo bench -p xhfs-core --bench io -- --quick
# then open target/criterion/read_large_64k/report/index.html

```