For bulk storage — VOD libraries, catch-up buffers, backup targets — ZFS RAID-Z2 is the sweet spot: it survives two simultaneous disk failures, has excellent data integrity via checksums, and scales to petabytes. This guide sets up a RAID-Z2 pool on Ubuntu for a storage server.
Prerequisites
- Ubuntu 22.04 with root access
- Multiple identical drives (minimum 4 for RAID-Z2; 6-12 is typical)
- At least 8 GB RAM (ZFS likes RAM — 1 GB per TB is a rough guideline for dedup, much less without)
Step 1 — Install ZFS
apt update
apt install -y zfsutils-linux
modprobe zfs
zfs versionStep 2 — Identify your drives
Never use `/dev/sdX` names for ZFS — they can change on reboot. Use /dev/disk/by-id/ which are stable:
ls -l /dev/disk/by-id/ | grep -v partYou'll see entries like ata-WDC_WD180EDGZ_XXXXXXX or nvme-Samsung_SSD_.... Note the ones for your data drives (not the OS drive).
Step 3 — Create the RAID-Z2 pool
RAID-Z2 uses 2 drives' worth of capacity for parity, surviving any 2 failures. With 8× 18 TB drives you get ~108 TB usable (6 × 18 TB):
zpool create -f -o ashift=12 tank raidz2 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE1 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE2 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE3 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE4 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE5 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE6 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE7 \
/dev/disk/by-id/ata-WDC_WD180EDGZ_DRIVE8ashift=12 forces 4K sector alignment — correct for all modern drives, and getting it wrong later means rebuilding the pool. Check the pool:
zpool status tank
zpool listStep 4 — Tune for a media/storage workload
Set a larger record size for large sequential files (video), enable compression (nearly free, helps even on video metadata), and disable atime (pointless write amplification):
zfs set recordsize=1M tank
zfs set compression=lz4 tank
zfs set atime=off tank
zfs set xattr=sa tankrecordsize=1M is ideal for streaming large files. If this pool will also hold a database or many small files, create a separate dataset with recordsize=16k for it.
Step 5 — Create datasets
Datasets are like folders with their own properties. Organize by workload:
zfs create tank/vod
zfs create tank/catchup
zfs create tank/backups
# Backups compress better with gzip
zfs set compression=gzip-6 tank/backupsThey mount automatically at /tank/vod, /tank/catchup, etc.
Step 6 — Add an NVMe cache (L2ARC) for hot reads
If your workload has hot content (top channels in catch-up, popular VOD), an NVMe read cache dramatically cuts HDD load. Add a spare NVMe as L2ARC:
zpool add tank cache /dev/disk/by-id/nvme-Samsung_SSD_980_CACHE
zpool status tankSize L2ARC at ~5-10% of pool size. For write-heavy workloads a separate SLOG device (mirror of two small fast SSDs) helps sync writes, but pure media serving rarely needs it.
Step 7 — Set up automatic scrubs
Scrubs read every block and verify checksums, catching silent corruption before it spreads. Schedule monthly:
# ZFS on Ubuntu ships a systemd timer — enable it
systemctl enable zfs-scrub-monthly@tank.timer
systemctl start zfs-scrub-monthly@tank.timer
# Run one now to establish a baseline
zpool scrub tank
zpool status tank # watch progressStep 8 — Monitor drive health
Set up email alerts for pool degradation. Edit /etc/zfs/zed.d/zed.rc:
ZED_EMAIL_ADDR="you@yourdomain.com"
ZED_NOTIFY_INTERVAL_SECS=3600
ZED_NOTIFY_VERBOSE=1
systemctl restart zfs-zedNow if a drive fails, ZED emails you immediately. With RAID-Z2 you have a 2-failure buffer, but you want to replace the first failed drive before a second dies.
Step 9 — Replacing a failed drive
When a drive fails, zpool status shows it as DEGRADED. Replace it:
# Offline the dead drive
zpool offline tank ata-WDC_WD180EDGZ_DEADDRIVE
# Physically swap the disk, then replace in the pool
zpool replace tank ata-WDC_WD180EDGZ_DEADDRIVE /dev/disk/by-id/ata-WDC_WD180EDGZ_NEWDRIVE
# Watch resilver progress
zpool status tankResilver on an 18 TB drive takes 24-48 hours. The pool stays online and readable throughout — RAID-Z2 means you can even lose another drive during resilver and survive.
Capacity planning reference
| Config | Raw | Usable (RAID-Z2) | Survives |
|---|---|---|---|
| 6× 18 TB | 108 TB | 72 TB | 2 failures |
| 8× 18 TB | 144 TB | 108 TB | 2 failures |
| 12× 18 TB | 216 TB | 180 TB | 2 failures |
Past 12 drives in a single vdev, split into multiple vdevs or use RAID-Z3 — resilver windows on very wide vdevs become a risk of their own. See our full storage sizing guide.
Where to go from here
Pair this with an NVMe hot tier for active data, or size a dedicated storage server with us. For the full storage math — catch-up growth, read budgets, cache hit ratios — read our storage sizing post.