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 version

Step 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 part

You'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_DRIVE8

ashift=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 list

Step 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 tank

recordsize=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/backups

They 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 tank

Size 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 progress

Step 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-zed

Now 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 tank

Resilver 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

ConfigRawUsable (RAID-Z2)Survives
6× 18 TB108 TB72 TB2 failures
8× 18 TB144 TB108 TB2 failures
12× 18 TB216 TB180 TB2 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.