ZFS (Zettabyte File System) is widely regarded as one of the most advanced file systems available for Linux. Originally developed by Sun Microsystems for Solaris, ZFS combines the roles of a traditional file system and a volume manager into a single, unified layer. This means you can create storage pools from multiple physical disks, manage logical volumes, enable built-in data compression, create instant snapshots, and detect and repair data corruption—all without needing separate tools like mdadm, LVM, or fsck.
While ZFS has historically been more common on FreeBSD and Solaris, the OpenZFS project has made it fully available on Ubuntu Linux. Since Ubuntu 19.10, Canonical has included official support for ZFS, making it accessible for both server and desktop environments. This guide covers installing ZFS on Ubuntu, creating storage pools, managing datasets, taking snapshots, and configuring data integrity features.
Why Choose ZFS Over ext4 or XFS
The default file systems on most Linux distributions—ext4 and XFS—are reliable and performant, but they lack several features that ZFS provides natively:
| Feature | ext4 / XFS | ZFS |
|---|---|---|
| Built-in RAID | Requires mdadm separately | Built-in (RAIDZ1, RAIDZ2, RAIDZ3, mirror) |
| Volume management | Requires LVM separately | Built-in pool and dataset management |
| Data integrity | No built-in checksumming | Every block is checksummed; silent corruption is detected automatically |
| Snapshots | LVM snapshots (with performance overhead) | Copy-on-write snapshots with zero initial overhead |
| Compression | Not built-in (requires application-level compression) | Transparent compression (LZ4, ZSTD, GZIP) |
| Self-healing | Not available | Automatic repair from redundant copies when corruption is detected |
| Send/Receive | Not available | Incremental snapshot replication to remote servers |
The most significant advantage is data integrity. Traditional file systems trust that the data written to disk is correct. ZFS does not. It checksums every block of data and metadata, and on every read, it verifies the checksum. If a block has been silently corrupted (a phenomenon known as “bit rot”), ZFS detects it immediately. If the pool has redundancy (mirror or RAIDZ), ZFS automatically repairs the corrupted block using a good copy—without any administrator intervention.
How to Install ZFS on Ubuntu
ZFS is available as a kernel module through the zfsutils-linux package on Ubuntu. Install it using the following commands:
sudo apt update
sudo apt install zfsutils-linux -y
Verify the installation:
zfs --version
This should display the ZFS version and the kernel module version. If the zfs command is not found, reboot the system to load the kernel module and try again.
Understanding ZFS Pools and Datasets
ZFS uses two primary concepts:
- Pool (zpool): A storage pool is a collection of one or more physical disks. The pool abstracts the underlying hardware, providing a single storage resource that ZFS manages. Pools can span multiple disks in various configurations (single disk, mirror, RAIDZ).
- Dataset: A dataset is a logical file system within a pool. Datasets are mounted as directories and can have individual properties (compression, quotas, snapshots). You can create as many datasets as you need without pre-allocating space—they share the pool’s storage dynamically.
Think of a pool as the physical storage and datasets as the logical partitions—except datasets are far more flexible than traditional partitions because they grow and shrink dynamically.
How to Create a ZFS Storage Pool
First, identify the available disks using lsblk:
lsblk -d -o NAME,SIZE,TYPE,MODEL
This lists all block devices on the system. Identify the disks you want to use for your ZFS pool. Warning: Creating a ZFS pool will destroy all existing data on the selected disks.
Single-Disk Pool (No Redundancy)
sudo zpool create datapool /dev/sdb
This creates a pool called datapool using a single disk. The pool is automatically mounted at /datapool. While this configuration provides ZFS’s checksumming and compression benefits, it has no redundancy—if the disk fails, data is lost.
Mirrored Pool (Two-Disk Redundancy)
sudo zpool create datapool mirror /dev/sdb /dev/sdc
A mirror writes identical copies to both disks. If one disk fails, the pool continues operating using the remaining disk. This is equivalent to RAID 1 but with ZFS’s additional data integrity features. The usable capacity equals the size of a single disk.
RAIDZ1 Pool (Three or More Disks)
sudo zpool create datapool raidz /dev/sdb /dev/sdc /dev/sdd
RAIDZ1 distributes data and parity across three or more disks, similar to RAID 5. It can survive the failure of one disk without data loss. The usable capacity is approximately (N-1) × disk size, where N is the number of disks.
For higher redundancy, use raidz2 (can survive two disk failures, requires four or more disks) or raidz3 (can survive three disk failures, requires five or more disks).
How to Create ZFS Datasets
Datasets are the logical file systems within a pool. Create datasets to organise your data logically:
sudo zfs create datapool/documents
sudo zfs create datapool/backups
sudo zfs create datapool/databases
Each dataset is automatically mounted as a subdirectory of the pool’s mount point:
/datapool/documents/datapool/backups/datapool/databases
Datasets share the pool’s total storage but can be individually configured with quotas, compression settings, and snapshot policies.
Enabling Compression
ZFS supports transparent compression—data is compressed as it is written and decompressed as it is read, without any application-level changes. The recommended compression algorithm is lz4, which provides an excellent balance between compression ratio and CPU usage:
sudo zfs set compression=lz4 datapool
This enables LZ4 compression on the entire pool. All existing data remains uncompressed, but all new data written to the pool will be compressed. To verify the compression ratio:
sudo zfs get compressratio datapool
For datasets containing highly compressible data (such as log files, database backups, or text documents), you can use the more aggressive zstd compression algorithm:
sudo zfs set compression=zstd datapool/backups
How to Create and Manage Snapshots
ZFS snapshots are one of its most powerful features. A snapshot captures the exact state of a dataset at a specific point in time. Because ZFS uses copy-on-write semantics, creating a snapshot is instantaneous and consumes no additional disk space—it only begins consuming space as the original data is modified.
Creating a Snapshot
sudo zfs snapshot datapool/documents@2026-08-24
The @ symbol separates the dataset name from the snapshot name. Use a descriptive name that includes the date or purpose of the snapshot.
Listing Snapshots
sudo zfs list -t snapshot
Accessing Snapshot Data
Every ZFS dataset contains a hidden .zfs/snapshot/ directory. To access the snapshot:
ls /datapool/documents/.zfs/snapshot/2026-08-24/
This directory contains a read-only view of the dataset as it existed when the snapshot was taken. You can copy individual files from the snapshot without restoring the entire dataset.
Rolling Back to a Snapshot
To restore a dataset to its exact state at the time of a snapshot:
sudo zfs rollback datapool/documents@2026-08-24
Warning: Rolling back destroys all data written after the snapshot was taken. This operation cannot be undone.
Deleting a Snapshot
sudo zfs destroy datapool/documents@2026-08-24
Setting Quotas and Reservations
ZFS datasets share the pool’s total space by default, but you can set quotas to prevent a single dataset from consuming all available storage:
# Set a 100 GB quota on the documents dataset
sudo zfs set quota=100G datapool/documents
# Guarantee 50 GB of reserved space for the databases dataset
sudo zfs set reservation=50G datapool/databases
A quota limits the maximum amount of space a dataset can consume. A reservation guarantees a minimum amount of space, even if other datasets attempt to fill the pool.
Checking Pool Health with zpool status
To monitor the health of your ZFS pool:
sudo zpool status
This command displays the pool’s state (ONLINE, DEGRADED, or FAULTED), the status of each disk, and any read/write/checksum error counts. A healthy pool shows all devices as ONLINE with zero errors.
If a disk is failing, the output shows a DEGRADED state with error counts. In a redundant pool (mirror or RAIDZ), you can replace the failing disk without downtime:
sudo zpool replace datapool /dev/sdc /dev/sde
This replaces /dev/sdc with /dev/sde and ZFS automatically begins resilverting (rebuilding) the data onto the new disk.
Scheduling Regular Scrubs for Data Integrity
A scrub is a ZFS operation that reads every block in the pool and verifies its checksum against the stored value. This is the primary mechanism for detecting and repairing silent data corruption (bit rot). If a corrupted block is found and the pool has redundancy, ZFS automatically repairs it.
To start a scrub manually:
sudo zpool scrub datapool
Schedule regular scrubs using a cron job or systemd timer. The recommended frequency is weekly for heavily used pools and monthly for archival storage. Ubuntu’s ZFS packages include a default scrub timer that runs monthly via /etc/cron.d/zfsutils-linux.
Replicating Snapshots to a Remote Server
ZFS’s send and receive commands allow you to replicate snapshots to a remote server, providing an efficient off-site backup strategy. The initial send transfers the full snapshot, and subsequent sends transfer only the incremental changes.
# Initial full send
sudo zfs send datapool/documents@snapshot1 | ssh user@backupserver sudo zfs receive backuppool/documents
# Incremental send (only changes since snapshot1)
sudo zfs send -i datapool/documents@snapshot1 datapool/documents@snapshot2 | \
ssh user@backupserver sudo zfs receive backuppool/documents
This is significantly more efficient than traditional file-based backup tools like rsync, because ZFS tracks changes at the block level rather than scanning every file for modifications.
ZFS Memory Considerations
ZFS uses a feature called the Adaptive Replacement Cache (ARC), which caches frequently accessed data in RAM. By default, ZFS will use up to 50% of the system’s total RAM for the ARC. On a server with 64 GB of RAM, ZFS might use up to 32 GB for caching.
While this dramatically improves read performance, it can cause memory pressure on systems running memory-intensive applications. To limit the ARC size, add the following to /etc/modprobe.d/zfs.conf:
options zfs zfs_arc_max=8589934592
This limits the ARC to 8 GB (the value is specified in bytes). After modifying this file, rebuild the initramfs and reboot:
sudo update-initramfs -u
sudo reboot
The general recommendation is to allocate at least 1 GB of RAM per 1 TB of storage managed by ZFS, with a practical minimum of 8 GB for any ZFS server.