Overview
WolfDisk is a distributed file system that provides easy-to-use shared and replicated storage across Linux machines. Mount a shared directory on any number of servers and have your data automatically synchronised. Built on the same proven consensus mechanisms as WolfScale.
🎬 Watch the overview video: WolfDisk on YouTube
Key Features
- FUSE-based — Mount as a regular Linux directory using FUSE3
- Content-addressed deduplication — Automatic deduplication via SHA256 hashing
- Chunk-based storage — Large files split into 4 MB chunks for efficient transfer and sync
- Leader / Follower / Client modes — Flexible node roles for any deployment
- Auto-discovery — UDP multicast for automatic peer discovery on LAN
- Automatic leader election & failover — Deterministic election with 2-second failover
- Delta sync — Incremental catchup — only missed changes are transferred
- S3-compatible REST API — Optional S3 gateway for any S3 client
- Bucket → folder mapping — Point any S3 bucket name at any folder
inside WolfDisk via
[s3.buckets] - LZ4 compression — Compressed network replication
- Symlink support — Full POSIX symlink support
- IBM Power ready — Pure Rust dependencies, builds natively on ppc64le
Node Roles
Every WolfDisk node operates in one of four roles:
| Role | Storage | Replication | Use Case |
|---|---|---|---|
| Leader | ✅ Yes | Broadcasts to followers | Primary write node |
| Follower | ✅ Yes | Receives from leader | Read replicas, failover candidates |
| Client | ❌ No | None (mount-only) | Access the drive remotely without local storage |
| Auto | ✅ Yes | Dynamic election | Default — lowest node ID automatically becomes leader |
💡 Client Mode is perfect for workstations or containers that just need to access the shared filesystem without storing data locally.
Quick Install
The interactive installer handles dependencies, compilation, configuration, and systemd service setup:
curl -sSL https://raw.githubusercontent.com/wolfsoftwaresystemsltd/WolfScale/main/wolfdisk/setup.sh | bash
The installer will prompt you for:
- Node ID — Unique identifier (defaults to hostname)
- Role — auto, leader, follower, or client
- Bind IP address — IP to listen on (auto-detected)
- Discovery method — Auto-discovery (UDP multicast), manual peers, or standalone
- Mount path — Where to mount the filesystem (default:
/mnt/wolfdisk)
⚠️ Compilation note: The installer compiles WolfDisk from source using Rust. This is CPU-intensive and may take several minutes. Please wait for it to complete.
Manual Installation
Prerequisites
- Linux with FUSE3 support
- Rust toolchain (
rustup)
⚠️ Running in an LXC Container?
WolfDisk requires the following features to be enabled in your container settings. Without these, WolfDisk will not start:
- ✅ TUN/TAP Device — Required for WolfDisk networking (
/dev/net/tun) - ✅ FUSE — Required for the FUSE filesystem mount (
/dev/fuse)
WolfStack: Go to the container → Settings → enable TUN/TAP Device and FUSE → save → reboot the container.
Proxmox: Go to the container → Options → Features → enable fuse and tun → reboot the container.
If installing via the WolfStack App Store, these settings are applied automatically.
Install Dependencies
# Ubuntu / Debian
sudo apt install libfuse3-dev fuse3
# Fedora / RHEL
sudo dnf install fuse3-devel fuse3
Build & Install
git clone https://github.com/wolfsoftwaresystemsltd/WolfScale.git
cd WolfScale/wolfdisk
cargo build --release
sudo cp target/release/wolfdisk /usr/local/bin/
sudo cp target/release/wolfdiskctl /usr/local/bin/
Docker Install (Unraid / Synology / TrueNAS / any Docker host)
For NAS platforms where compiling from source isn’t practical, WolfDisk ships as a prebuilt multi-arch Docker image alongside WolfNet. Pair them to join a NAS to your WolfStack cluster overlay:
docker run -d --name wolfdisk \
--restart unless-stopped \
--privileged --network host \
--device /dev/fuse:/dev/fuse \
-v wolfdisk-config:/etc/wolfdisk \
-v wolfdisk-data:/var/lib/wolfdisk \
-v /mnt/wolfdisk:/mnt/wolfdisk:rshared \
-e WOLFDISK_ROLE=client \
-e WOLFDISK_PEERS=<leader_ip:8550> \
ghcr.io/wolfsoftwaresystemsltd/wolfdisk:latest
Or use the satellite compose file from the WolfStack repo to bring up WolfNet and WolfDisk together in one go:
WOLFNET_JOIN_TOKEN=<token> WOLFDISK_LEADER=<leader_ip:8550> \
docker compose -f docker-compose.satellite.yml up -d
Multi-arch: the image works on linux/amd64 and linux/arm64. Get the join token from the WolfStack UI or by running wolfnet invite on any cluster node.
Usage
1. Initialize Data Directory
wolfdisk init -d /var/lib/wolfdisk
2. Mount the Filesystem
# Foreground (for testing)
sudo wolfdisk mount -m /mnt/wolfdisk
# As a systemd service (recommended)
sudo systemctl start wolfdisk
3. Check Status
wolfdiskctl status
4. Use It Like Any Directory
# Write files
echo "Hello, WolfDisk!" > /mnt/wolfdisk/hello.txt
cp /var/log/syslog /mnt/wolfdisk/
# Read files — automatically available on all nodes
cat /mnt/wolfdisk/hello.txt
ls -la /mnt/wolfdisk/
Configuration
WolfDisk is configured via /etc/wolfdisk/config.toml. The installer creates this file
for you, or you can edit it manually:
[node]
id = "node1" # Unique node identifier
role = "auto" # auto, leader, follower, or client
bind = "0.0.0.0:8550" # IP and port for cluster communication
data_dir = "/var/lib/wolfdisk" # Where chunks and index are stored
[cluster]
# Auto-discovery (recommended for LAN)
discovery = "udp://239.255.0.1:8551"
# Or manual peers (for cross-subnet / WAN)
# peers = ["192.168.1.10:8550", "192.168.1.11:8550"]
[replication]
mode = "shared" # "shared" or "replicated"
factor = 3 # Number of copies (replicated mode)
chunk_size = 4194304 # 4 MB chunks
[mount]
path = "/mnt/wolfdisk"
allow_other = true # Allow other users to access the mount
# Optional: S3-compatible API
[s3]
enabled = true
bind = "0.0.0.0:9878"
# access_key = "your-access-key" # optional auth
# secret_key = "your-secret-key" # optional auth
Configuration Reference
| Section | Key | Default | Description |
|---|---|---|---|
[node] |
id |
hostname | Unique identifier — used in leader election (lowest ID wins) |
role |
auto |
auto, leader, follower, or client
|
|
bind |
0.0.0.0:8550 |
Listen address for cluster communication | |
data_dir |
/var/lib/wolfdisk |
Directory for chunks, index, and WAL | |
[cluster] |
discovery |
— | UDP multicast address for auto-discovery |
peers |
[] |
Manual list of peer addresses | |
[replication] |
mode |
shared |
shared (single leader) or replicated (N copies) |
factor |
3 |
Replication factor for replicated mode | |
chunk_size |
4194304 |
Chunk size in bytes (4 MB) | |
[mount] |
path |
/mnt/wolfdisk |
FUSE mount point |
allow_other |
true |
Allow other system users to access the mount | |
[s3] |
enabled |
false |
Enable S3-compatible REST API |
bind |
0.0.0.0:9878 |
S3 API listen address | |
access_key |
— | Optional S3 access key | |
secret_key |
— | Optional S3 secret key | |
[s3.buckets] |
name = "folder" |
— | Optional bucket → folder map (e.g. photos = "/data/photos"); paths are
from the WolfDisk root. See Mapping Buckets to Folders
below |
Architecture
WolfDisk is composed of several layers that work together:
How It Works
- FUSE Layer — Applications read/write to
/mnt/wolfdisklike a normal directory. The FUSE driver intercepts all filesystem calls. - Chunk Store — Files are split into 4 MB chunks, each identified by its SHA256 hash. Identical data is automatically deduplicated.
- File Index — Maps file paths to their chunk references, permissions, size, and modification times.
- Replication Engine — Synchronises chunks and index updates across nodes. Handles leader election and failover.
- Network Layer — UDP multicast for peer discovery, TCP for data transfer. LZ4 compression for network efficiency.
Leader Election & Failover
WolfDisk uses deterministic leader election — no voting, no delays. The node with the lowest ID is always the leader.
How Failover Works
- Heartbeat timeout — Nodes monitor the leader with a 2-second timeout
- Fast election — No voting or consensus delay; lowest node ID always wins
- Seamless reads — Followers continue serving reads during failover
- Explicit override — Set
role = "leader"to force a specific node as leader
Sync & Replication
Write Replication
When the leader writes a file:
- Local write — Leader stores chunks and updates the file index locally
- Broadcast — Leader sends the index update and chunk data to all followers
- Apply — Followers update their local index and store the chunks
Delta Sync (Catchup)
When a node starts or recovers from downtime, it performs an incremental sync:
Only missed changes are transferred — a node that was down briefly doesn't need to re-download everything.
Read Caching
Followers cache chunks locally for fast reads:
- Cache hit — Chunk exists locally → return immediately
- Cache miss — Fetch chunk from leader → cache locally → return
Client Mode (Thin Client)
Client mode mounts the filesystem without storing any data locally. All reads and writes are forwarded to the leader over the network.
| Aspect | Leader / Follower | Client |
|---|---|---|
| Local Storage | ✅ Stores data on disk | ❌ No local storage |
| Reads | Served locally | Forwarded to leader |
| Writes | Local (leader) or forwarded | Forwarded to leader |
| Use Case | Data nodes, replicas | Workstations, containers |
Client mode is ideal for:
- Workstations accessing shared files
- Containers that need cluster storage access
- Read-heavy applications where network latency is acceptable
S3-Compatible API
WolfDisk can optionally expose an S3-compatible REST API, allowing any S3 client (AWS CLI, rclone, MinIO Client, etc.) to read and write files. Both FUSE and S3 access the same underlying data — files written via FUSE are instantly visible through S3, and vice versa.
Enable S3
Add to /etc/wolfdisk/config.toml:
[s3]
enabled = true
bind = "0.0.0.0:9878"
# Optional authentication:
# access_key = "your-access-key"
# secret_key = "your-secret-key"
How It Maps
| WolfDisk | S3 Equivalent |
|---|---|
| Top-level directory | Bucket |
| File in directory | Object |
| Nested directory | Object key prefix |
Buckets
By default, every top-level directory in WolfDisk is a bucket, and the files inside
it are objects (nested folders become object key prefixes). Create a directory called
backups and you immediately have a backups bucket — there is no separate
“create bucket” step. ListBuckets returns every top-level directory it
finds, plus any bucket you map explicitly (below).
Mapping Buckets to Folders
You don’t have to expose your folders at the top level. The optional [s3.buckets]
table maps a bucket name to any folder inside WolfDisk, so a client connecting to bucket
photos can be served from a nested path such as /data/photos:
[s3]
enabled = true
bind = "0.0.0.0:9878"
# Map bucket names to specific folders inside WolfDisk.
# Paths are interpreted from the WolfDisk root; leading/trailing slashes are ignored.
[s3.buckets]
photos = "/data/photos"
backups = "/srv/backups"
media = "tenants/acme/media"
- Listed buckets serve their mapped folder — a client using bucket
photosreads and writes under/data/photos, not a top-levelphotosdirectory. - Unlisted buckets are unchanged — any bucket not in the table still maps to a top-level directory of the same name (the default behaviour), so existing setups keep working exactly as before.
- Mapped buckets always appear in
ListBuckets— even when the target folder isn’t a top-level directory of the same name, so S3 clients can still discover them. - Paths are relative to the WolfDisk root — leading and trailing slashes are
ignored, so
"/data/photos"and"data/photos/"are equivalent.
💡 Edit from the WolfStack dashboard: open the node’s WolfDisk → Configuration → S3-Compatible Gateway section and use the Bucket → Folder Mappings editor to add, change, or remove mappings without hand-editing the TOML. Removing a row deletes that mapping; restart WolfDisk to apply the change.
This is handy for serving a single sub-tree to an S3 client, giving each tenant or app its own bucket name that points at its own folder, or keeping bucket names stable while you reorganise the underlying directories.
Supported Operations
| Operation | Method | Path |
|---|---|---|
| ListBuckets | GET |
/ |
| CreateBucket | PUT |
/bucket |
| DeleteBucket | DELETE |
/bucket |
| HeadBucket | HEAD |
/bucket |
| ListObjectsV2 | GET |
/bucket?prefix=... |
| GetObject | GET |
/bucket/key |
| PutObject | PUT |
/bucket/key |
| DeleteObject | DELETE |
/bucket/key |
| HeadObject | HEAD |
/bucket/key |
Examples
# Using AWS CLI
aws --endpoint-url http://localhost:9878 s3 ls
aws --endpoint-url http://localhost:9878 s3 cp file.txt s3://mybucket/file.txt
aws --endpoint-url http://localhost:9878 s3 ls s3://mybucket/
# Using curl
curl http://localhost:9878/mybucket/myfile.txt
curl -X PUT --data-binary @file.txt http://localhost:9878/mybucket/file.txt
CLI Reference
wolfdisk (Service Daemon)
| Command | Description |
|---|---|
wolfdisk init -d PATH |
Initialize a new WolfDisk data directory |
wolfdisk mount -m PATH |
Mount the filesystem at the given path |
wolfdisk unmount -m PATH |
Unmount the filesystem |
wolfdisk status |
Show node configuration |
Options:
--config PATH— Path to config file (default:/etc/wolfdisk/config.toml)
wolfdiskctl (Control Utility)
| Command | Description |
|---|---|
wolfdiskctl status |
Show live status from the running service (role, state, version, file count, size, peers) |
wolfdiskctl list servers |
List all discovered servers in the cluster with roles and status |
wolfdiskctl stats |
Live cluster statistics dashboard (refreshes every second, Ctrl+C to exit) |
Options:
-s, --status-file PATH— Path to status file (default:/var/lib/wolfdisk/cluster_status.json)
Systemd Service
The installer creates a systemd service for you automatically. Common commands:
# Start WolfDisk
sudo systemctl start wolfdisk
# Check status
sudo systemctl status wolfdisk
# View logs
sudo journalctl -u wolfdisk -f
# Enable on boot
sudo systemctl enable wolfdisk
# Restart after config change
sudo systemctl restart wolfdisk
Multi-Node Setup
A typical deployment has multiple nodes with different roles. All nodes with
role = "auto" will automatically elect a leader.
Server 1 (will become leader — lowest ID)
[node]
id = "node-a"
role = "auto"
bind = "192.168.1.10:8550"
data_dir = "/var/lib/wolfdisk"
[cluster]
discovery = "udp://192.168.1.10:8551"
[mount]
path = "/mnt/shared"
Server 2–N (will become followers — higher IDs)
[node]
id = "node-b" # Higher ID → follower
role = "auto"
bind = "192.168.1.11:8550"
data_dir = "/var/lib/wolfdisk"
[cluster]
discovery = "udp://192.168.1.11:8551"
[mount]
path = "/mnt/shared"
Workstation (client only — no storage)
[node]
id = "desktop"
role = "client"
bind = "192.168.1.50:8550"
[cluster]
peers = ["192.168.1.10:8550", "192.168.1.11:8550"]
[mount]
path = "/mnt/shared"
WolfStack Dashboard
When WolfStack is installed, WolfDisk gets a dedicated cluster management page in the dashboard. You can manage every aspect of your WolfDisk deployment — across hosts, Docker containers, and LXC containers — from a single pane of glass.
Cluster Overview
The dashboard shows a summary of your entire WolfDisk deployment at a glance:
- Installed nodes — How many hosts and containers have WolfDisk installed
- Running / Stopped — Service status across all nodes
- Active clusters — Number of distinct WolfDisk clusters (e.g. “fast-nvme”, “bulk-hdd”)
- Mounted filesystems — Total active WolfDisk mounts
Nodes are grouped by cluster name, so you can see at a glance which servers belong to which storage pool.
Node Management
Each node — whether a bare-metal host, Docker container, or LXC container — is shown in a table with:
| Column | Description |
|---|---|
| Status | Running, stopped, failed, or offline indicator |
| Node Name | Hostname or container name |
| Member Type | Host, Docker, or LXC badge |
| Version | Installed version with upgrade indicator when a newer release is available |
| Role | Leader, Follower, Client, or Auto |
| Actions | Start, stop, restart, configure, upgrade |
Click any node to expand its detail panel, which shows the full configuration summary: data directory, mount point, bind address, WolfNet mesh address (if configured), replication mode and factor, peer list, and S3 API status.
Configuration Editor
The built-in configuration dialog provides a structured form for editing /etc/wolfdisk/config.toml
on any node — no SSH required. Configuration is split into logical sections:
- Node — Node ID, role, bind address, data directory
- Cluster — Cluster name, peer discovery settings, peer list with a checkbox picker for known nodes
- Replication — Mode (shared / replicated) and replication factor
- Mount — Mount path, allow_other flag
- S3 — Enable/disable S3 API, custom bind address
Diagnostics
Before starting a node, you can run the built-in configuration diagnostics tool. It validates:
- Node ID is set
- Bind address format and port validity
- Data directory and mount path are configured
- Peer address formats are correct
- The
wolfdiskbinary is installed - No port conflicts with other services
- Multi-user access permissions (FUSE
allow_other)
Diagnostics run remotely against the target node in real time, so you catch misconfigurations before they cause failures.
One-Click Install & Upgrade
Install WolfDisk on new hosts or containers directly from the dashboard:
- Configure — Set the cluster name, peers, replication mode, and mount path
- Install — WolfStack compiles and installs WolfDisk with a live terminal view
- Auto-join — If only one WolfDisk cluster exists, new nodes automatically join it
When a newer version is available on GitHub, an upgrade badge appears next to each node. Click Upgrade to pull the latest source, recompile, and restart the service — your configuration is preserved automatically.
💡 Container support: WolfStack automatically enables TUN and FUSE device access when installing WolfDisk into Docker or LXC containers, so you don’t need to configure these manually.
Troubleshooting
WolfDisk fails to start in an LXC container
If WolfDisk fails immediately or you see errors about /dev/fuse or /dev/net/tun not being available, the container is missing required device access:
- Stop the container
- Go to the container's Settings page
- Enable TUN/TAP Device and FUSE
- Save and start the container
On Proxmox: Options → Features → fuse, tun. On WolfStack: Settings → TUN/TAP Device ✅, FUSE ✅.
Mount fails with "Transport endpoint not connected"
The FUSE mount is stale. Unmount and remount:
sudo fusermount -u -z /mnt/wolfdisk
sudo systemctl restart wolfdisk
Permission denied on mount
Ensure user_allow_other is enabled:
echo "user_allow_other" | sudo tee -a /etc/fuse.conf
Peers not discovering each other
- Check that port 8550 (TCP) and 8551 (UDP) are open in your firewall
- For cross-subnet setups, use
peers = [...]instead of UDP discovery - Verify
bindis set to an accessible IP, not127.0.0.1
Status file not found
If wolfdiskctl status reports "Status file not found", the service is not running:
sudo systemctl start wolfdisk
sudo journalctl -u wolfdisk -f # Check for errors
Client Reset
If a client node (not leader/follower!) has a stuck mount or corrupted cache, use the reset script:
sudo bash /opt/wolfscale-src/wolfdisk/reset_client.sh
⚠️ Warning: The reset script wipes /var/lib/wolfdisk. Only use it
on client nodes. Running it on a leader or follower will cause data
loss.
Network Ports
| Port | Protocol | Purpose |
|---|---|---|
| 8550 | TCP | Cluster communication (data, replication, sync) |
| 8551 | UDP | Auto-discovery (multicast) |
| 9878 | TCP | S3-compatible API (when enabled) |