Unraid Wants $129. Your Drives Want Freedom.
You’ve got a server with four drives from three different eras — a 4TB you yanked from a dead NAS, a couple 8TBs you snagged on Black Friday, and a random 2TB doing absolutely nothing in a drawer. You want a unified pool. You want parity protection so one drive failure doesn’t ruin your movie collection and twenty years of photos. You do not want to rebuild your entire array when you add a new drive, and you really don’t want to pay $129 for a license to do something Linux has been able to do for free since before Unraid existed.
Enter mergerfs and SnapRAID. Two tools that were practically designed for each other, even though they’re completely independent projects. mergerfs handles the union mount — your four separate disks look like one big pool. SnapRAID handles parity — one drive’s worth of protection, computed on a schedule, so a failure doesn’t destroy everything.
It’s not perfect. We’ll get to what it’s bad at. But for the average homelab with a few large drives full of media, backups, and archives, this stack is hard to beat.
What You’re Actually Building
Before the commands, a quick mental model:
mergerfs is a FUSE-based union filesystem. You mount /mnt/disk1, /mnt/disk2, /mnt/disk3, and /mnt/disk4 — any drives, any sizes, any filesystems (ext4, xfs, whatever) — and mergerfs presents them all as /mnt/pool. Files land on individual disks. mergerfs just makes the filesystem layer pretend they’re one. No striping. No RAID. No magic. Just a transparent union.
SnapRAID computes parity files across your data disks and stores them on a dedicated parity disk. Once a day (or however often you schedule it), you run snapraid sync — it reads all your data disks, computes parity, updates the parity disk. If a data disk dies, snapraid fix uses the remaining disks plus parity to reconstruct what was lost.
The key insight: parity is computed on a schedule, not in real time. This is the fundamental trade-off. More on that in a minute.
How It Compares to the Alternatives
| Setup | Drive Size Flexibility | Realtime Parity | Recovery Speed | Cost |
|---|---|---|---|---|
| mergerfs + SnapRAID | Any mix | No | Moderate | $0 |
| Unraid | Any mix | No (parity on demand) | Moderate | $59–$129 |
| ZFS raidz1 | Same size preferred | Yes | Slow rebuild | $0 (but RAM hungry) |
| btrfs raid5/6 | Flexible | Yes (write hole bug) | Don’t trust it | $0 (but risky) |
| Hardware RAID | Matched drives | Yes | Fast | $50–$300+ |
ZFS is excellent but opinionated — it wants same-size drives for efficiency, it wants a lot of RAM, and it’ll rebuild an entire vdev if a drive fails (which is a multi-day stress event on a large array). btrfs raid5/6 has had a known write hole bug for years; I wouldn’t trust it with data I care about. Hardware RAID locks you into a controller, and if the controller dies, you need that exact same card to read your data. Good luck finding a discontinued LSI on eBay in five years.
Unraid is actually the closest competitor here — it does the same scheduled parity thing — but you’re paying for their UI, their plugin ecosystem, and the license. If you want a web UI and curated plugins, Unraid is totally worth it. If you want to understand what’s happening and keep your existing Debian or Ubuntu install, you don’t need it.
Installing the Tools
On Debian/Ubuntu:
# mergerfsapt install mergerfs
# SnapRAID (not in main repos on older Distros — grab from GitHub releases)wget https://github.com/amadvance/snapraid/releases/download/v11.6/snapraid-11.6.tar.gztar xf snapraid-11.6.tar.gzcd snapraid-11.6./configuremakemake installOn newer Debian/Ubuntu you can sometimes get SnapRAID from the repos, but the version is often behind. The upstream release is straightforward to compile and it has no exotic dependencies.
Setting Up Your Disks
Assume you have four drives. Three will be data disks, one will be the parity disk. The parity disk must be at least as large as your largest data disk — it doesn’t need to match, just needs to be big enough.
Format your data disks as ext4 (or xfs — both work fine with mergerfs):
mkfs.ext4 -L disk1 /dev/sdbmkfs.ext4 -L disk2 /dev/sdcmkfs.ext4 -L disk3 /dev/sddmkfs.ext4 -L parity /dev/sdeCreate mount points and mount them:
mkdir -p /mnt/disk{1,2,3} /mnt/parity /mnt/pool
# Add to /etc/fstab (use your actual UUIDs — never /dev/sdX in fstab)# blkid to get UUIDsblkid /dev/sdb /dev/sdc /dev/sdd /dev/sdeIn /etc/fstab:
UUID=aaaa-1111 /mnt/disk1 ext4 defaults,nofail 0 2UUID=bbbb-2222 /mnt/disk2 ext4 defaults,nofail 0 2UUID=cccc-3333 /mnt/disk3 ext4 defaults,nofail 0 2UUID=dddd-4444 /mnt/parity ext4 defaults,nofail 0 2Mount everything:
mount -aConfiguring mergerfs
Here’s where people copy-paste a mergerfs mount line from Stack Overflow and end up confused about why files aren’t landing where they expect. The mount options matter.
Add this to /etc/fstab:
/mnt/disk1:/mnt/disk2:/mnt/disk3 /mnt/pool fuse.mergerfs defaults,allow_other,use_ino,cache.files=off,dropcacheonclose=true,category.create=epmfs,moveonenospc=true,fsname=mergerfsPool 0 0Let’s break down the non-obvious ones:
category.create=epmfs — “existing path, most free space.” When a new file is written to the pool, mergerfs picks the disk that already has the most content from that directory path. If it’s a brand new path with no existing content, it falls back to most free space. This keeps related files together on the same disk instead of scattering everything randomly. Your movie library doesn’t end up split across three drives.
moveonenospc=true — If a file write fails because the target disk is full, mergerfs will transparently move it to another disk mid-write. Without this, you’d get a cryptic “no space left on device” even though you have 2TB free on disk2. This should always be on.
dropcacheonclose=true — Tells the kernel to drop page cache entries when files are closed. Without this, the OS may cache data that’s already been written to disk, leading to stale reads in some edge cases with FUSE. Minor, but worth having on a storage server.
cache.files=off — Disables mergerfs’s own file caching. Combined with dropcacheonclose, this makes mergerfs fully pass-through. For a NAS use case serving Plex/Jellyfin or Samba shares, you want the OS cache, not a double-cache.
use_ino — Use the underlying disk’s inode numbers instead of generating new ones. Important for tools that track files by inode.
Mount it:
mount /mnt/pool# Ormount -aNow df -h /mnt/pool should show the combined capacity of all three data disks.
Configuring SnapRAID
Create /etc/snapraid.conf:
# Parity file — on your dedicated parity diskparity /mnt/parity/snapraid.parity
# Content files — SnapRAID needs at least one, put extras on data disks as backupcontent /var/snapraid/snapraid.contentcontent /mnt/disk1/snapraid.contentcontent /mnt/disk2/snapraid.content
# Data disks — one line per disk, with a unique labeldata d1 /mnt/disk1data d2 /mnt/disk2data d3 /mnt/disk3
# Exclude patterns — files that change constantly (databases, torrents, etc.)exclude /tmp/exclude /lost+found/exclude *.!qBexclude *.partexclude .Trash-*/exclude /downloads/incomplete/
# Block size in KB (default 256 is fine for most setups)blocksize 256Create the content directory:
mkdir -p /var/snapraidRun your first sync (this will take a while — it’s reading and computing parity for all existing data):
snapraid syncGo make coffee. Come back. If it completes without errors, you have parity protection. Run a scrub to verify:
snapraid scrub -p 100 -o 0This reads 100% of your array and verifies parity matches data. Good baseline to confirm the setup is clean.
Automating Sync with snapraid-runner
The community-maintained snapraid-runner script handles the automation most people want: sync on a schedule, email you if something looks wrong, scrub periodically. It’s a Python script, not a daemon, and it’s exactly the right tool for this.
git clone https://github.com/Chronial/snapraid-runner.git /opt/snapraid-runnercp /opt/snapraid-runner/snapraid-runner.conf.example /etc/snapraid-runner.confEdit /etc/snapraid-runner.conf:
[snapraid]executable = /usr/bin/snapraidconfig = /etc/snapraid.conf
[logging]file = /var/log/snapraid-runner.logmaxsize = 5
[email]enabled = false# Set to true and fill in your SMTP details if you want reports
[scrub]enabled = truepercentage = 22older-than = 7The scrub config above runs a scrub of 22% of the array on each sync run, cycling through everything over about 4–5 runs. This is the recommended approach — a full scrub on every run on a large array takes forever.
Add a cron job to run it nightly:
crontab -e0 3 * * * python3 /opt/snapraid-runner/snapraid-runner.py -c /etc/snapraid-runner.conf3 AM. Every night. The parity is fresh by morning.
When a Drive Actually Dies
Here’s the scenario: /mnt/disk2 is dead. The drive makes the noise. SMART says the drive is gone. You’ve got parity computed as of last night’s sync run.
Step 1: Don’t panic. Don’t run sync. If you sync with a missing/failed disk before recovering, SnapRAID will update parity to reflect the missing data. You lose your recovery window.
Step 2: Assess the damage. Anything written after the last sync is gone. That’s the trade-off you accepted.
snapraid statusStep 3: Mount the replacement drive. Get a new drive (at least as large as the failed one), format it, mount it at /mnt/disk2.
Step 4: Fix it.
snapraid fix -d d2SnapRAID reads all remaining data disks plus the parity disk and reconstructs the missing data onto /mnt/disk2. Depending on your array size, this takes hours. It’s not fast, but it works.
Step 5: Verify.
snapraid check -d d2If this comes back clean, you’re restored. Run a full sync to update parity with the new drive’s position.
One important nuance: if you want to add a new disk to expand the pool, that’s mostly a mergerfs operation (add it to the fuse.mergerfs line in fstab, add it to snapraid.conf, run sync). SnapRAID handles arrays up to six parity disks if you want more redundancy, but one parity disk is the common homelab setup.
When This Stack Is Wrong for You
Be honest with yourself here.
You have a database, a download client, or any workload that chews through small files constantly. SnapRAID’s parity is always stale relative to writes since the last sync. If your drive dies between syncs and you had a bunch of new torrent downloads or database transactions, those files are gone. Downloads are recoverable. Your Immich database is not. Keep databases on a separate disk with actual realtime backup (rsync, restic, whatever), outside the SnapRAID pool.
You need realtime RAID. If you genuinely need every write protected the moment it hits disk — production NAS, small business file server — you want ZFS mirror or raidz, or real hardware RAID. SnapRAID’s scheduled model is a deliberate design choice, not a bug, but it’s not for every workload.
Your array is enormous and sync takes longer than 24 hours. If a nightly sync runs into the next day’s sync window, you’ve got a problem. Tune the exclude rules aggressively and consider whether you need a second parity disk to reduce how much SnapRAID has to recompute on each run.
You want a nice web UI and one-click plugin installs. That’s Unraid’s value proposition and it’s a real one. The $129 license is a fair price for what they’ve built. No shame in paying for software that saves you hours of CLI wrangling.
The Bottom Line
mergerfs + SnapRAID hits a sweet spot that’s hard to find elsewhere: any drive sizes, any filesystem, no proprietary lock-in, parity protection that actually works, and zero licensing cost. For a homelab NAS storing media, photos, and backups where the occasional lost upload between syncs is acceptable, it’s the right call almost every time.
The mental model is simple once you internalize it: mergerfs is just a lens that makes your drives look like one. SnapRAID is a nightly checkpoint. You’re not running realtime RAID — you’re running a very fast, disk-level backup that can reconstruct a failed drive. Know what you signed up for and it’ll serve you for years.
The setup takes maybe an hour. The maintenance is a cron job. The recovery, if you ever need it, is a single command and a few hours of patience. For the price of a few drives you probably already own, that’s a hell of a deal.