ZFS is a combined file system and logical volume manager renowned for its data integrity guarantees, transparent compression, built-in snapshotting, and copy-on-write architecture. While ZFS is not included in the RHEL 8 kernel, the OpenZFS project provides compatible DKMS packages that build the kernel module on demand. This tutorial covers adding the OpenZFS repository, installing the zfs package, creating a zpool across raw block devices, creating datasets with compression and quotas, and managing snapshots, rollbacks, and clones — all on a standard RHEL 8 system.

Prerequisites

  • RHEL 8 server with at least one spare, unpartitioned block device (e.g., /dev/sdb)
  • Root or sudo access
  • Internet access to reach zfsonlinux.org and dl.fedoraproject.org
  • EPEL 8 repository enabled for DKMS dependencies (dnf install -y epel-release)
  • Running kernel headers matching the active kernel (dnf install -y kernel-devel)

Step 1 — Add the OpenZFS Repository and Install ZFS

The OpenZFS project publishes an RPM repo for each RHEL/EL release. Install the repo package directly by URL, then use dnf to pull in the zfs package. The DKMS build step compiles the kernel module for your current kernel version and may take a minute or two.

# Add the OpenZFS EL8 repository
dnf install -y https://zfsonlinux.org/epel/zfs-release-2_2.el8.noarch.rpm

# Install kernel headers and DKMS first (EPEL dependency)
dnf install -y epel-release kernel-devel dkms

# Install ZFS (triggers DKMS module build)
dnf install -y zfs

# Verify the package installed correctly
rpm -q zfs

Step 2 — Load the ZFS Kernel Module

After installation, load the zfs kernel module with modprobe and confirm it is present. Adding zfs to /etc/modules-load.d/ ensures it loads automatically on every subsequent boot.

# Load the module for the current session
modprobe zfs

# Confirm the module is loaded
lsmod | grep zfs

# Persist across reboots
echo "zfs" > /etc/modules-load.d/zfs.conf

# Verify ZFS utilities are functional
zpool version

Step 3 — Create a ZFS Pool

A zpool is the top-level ZFS storage container that maps to one or more block devices. The simplest single-disk pool is created with zpool create. For redundancy in production, use mirror or raidz layouts. The pool is mounted at /myzpool by default.

# Single-disk pool (development/testing)
zpool create myzpool /dev/sdb

# Mirror pool with two disks (recommended minimum for production)
# zpool create myzpool mirror /dev/sdb /dev/sdc

# RAIDZ (RAID-5 equivalent) with three disks
# zpool create myzpool raidz /dev/sdb /dev/sdc /dev/sdd

# Check pool status
zpool status myzpool

# View pool I/O statistics
zpool iostat myzpool 2

Step 4 — Create Datasets and Set Properties

ZFS datasets are hierarchical namespaces inside a pool. Each dataset inherits pool properties but can override them individually. Enable lz4 compression and set a quota to prevent a single dataset from consuming the entire pool.

# Create a dataset
zfs create myzpool/dataset

# Enable lz4 compression (fast, excellent ratio for most data)
zfs set compression=lz4 myzpool/dataset

# Set a 20 GB quota so this dataset cannot exceed 20 GB
zfs set quota=20G myzpool/dataset

# Override the default mount point
zfs set mountpoint=/srv/data myzpool/dataset

# Verify all properties
zfs get all myzpool/dataset | grep -E 'compression|quota|mountpoint|used|avail'

# List all datasets
zfs list

Step 5 — Manage Snapshots

ZFS snapshots are instant, space-efficient read-only copies of a dataset at a point in time. They consume only the space needed to store changed blocks since the snapshot was taken. You can roll back a dataset to any snapshot or clone it into a writable copy.

# Take a snapshot (naming convention: dataset@label)
zfs snapshot myzpool/dataset@before-update

# List all snapshots
zfs list -t snapshot

# Roll back to a previous snapshot (destroys intermediate changes)
zfs rollback myzpool/dataset@before-update

# Clone a snapshot into a new writable dataset
zfs clone myzpool/dataset@before-update myzpool/dataset-clone

# Destroy a snapshot when no longer needed
zfs destroy myzpool/dataset@before-update

Step 6 — Monitor Pool Health and Scrub

ZFS checksums every block on write. A periodic scrub reads all data and verifies checksums, repairing any detected corruption using redundancy data. Schedule monthly scrubs via cron or systemd timer for ongoing data integrity assurance.

# Start an online scrub (runs in background)
zpool scrub myzpool

# Watch scrub progress
zpool status myzpool

# View pool-level I/O statistics (refresh every 2 seconds, 5 times)
zpool iostat myzpool 2 5

# Check how much space is used vs available
zfs list -o name,used,avail,refer,mountpoint

# Export the pool safely (e.g., before moving disks)
zpool export myzpool

# Re-import the pool
zpool import myzpool

Conclusion

You have added the OpenZFS repository on RHEL 8, installed and loaded the ZFS kernel module via DKMS, created a zpool backed by a block device, and built a dataset with LZ4 compression, quotas, and a custom mount point. You also practiced the snapshot, rollback, and clone workflow that makes ZFS invaluable for safe system administration, and learned how to monitor pool health with zpool status and zpool iostat. This foundation supports everything from simple single-disk workstation pools to large multi-disk RAIDZ storage servers on RHEL 8.

Next steps: Configuring ZFS Replication with zfs send/receive, Setting Up NFS Exports from a ZFS Dataset on RHEL 8, and Automating ZFS Snapshots with Systemd Timers.