Installing and using ZFS on Ubuntu for reliable local storage

ZFS has earned a reputation among Linux power users for combining storage, snapshots, and integrity checking into a single coherent toolkit. For Ubuntu adopters who treat their machines as long-term workstations or home servers, the filesystem brings features that historically required separate products: RAID-style redundancy, built-in checksumming, transparent compression, and instant point-in-time snapshots.

This guide walks through installing ZFS on Ubuntu, building a usable storage pool, and exercising the daily features that make it worthwhile. It assumes a standard Ubuntu 22.04 or 24.04 install and stays close to the commands you would actually type, including a few notes for setups common in Australian homes and small offices.

What ZFS actually gives you

ZFS is a combined volume manager and filesystem, which means it handles both the question of "which disks belong together" and "how files are stored on those disks." That dual role is what makes it different from using ext4 on top of mdadm or LVM. There is one tool, called zpool, that owns disk redundancy, and another, called zfs, that owns the filesystems living on top of it.

The features most people care about fall into a handful of categories. Copy-on-write means the filesystem never overwrites live data, so a sudden power loss cannot corrupt the file you were saving. Checksums at every block mean silent disk corruption gets caught instead of propagating. Snapshots are nearly free because they record deltas rather than copying whole files. Compression, deduplication, and encryption can be turned on per dataset, giving fine-grained control over how different folders behave.

For Australian households, this matters in practical ways. A typical NBN connection in a Sydney or Brisbane apartment can wobble through peak evening hours, and so do the cheap surge-protected powerboards many homes rely on. ZFS tolerates both better than ext4, because its transaction groups commit atomically and a manual scrub repairs detected errors from parity rather than waiting for you to notice. If you keep a Plex library, photo archive, or small-business records on a home server, those properties buy you peace of mind without buying enterprise hardware.

Preparing your Ubuntu installation

Ubuntu ships ZFS support split across two packages: zfsutils-linux for the userland tools, and matching kernel modules that arrive through the regular kernel updates. On a fresh install, only the userland package needs installing; the modules are pulled in as a dependency and updated whenever the kernel does.

Open a terminal and refresh the package index, then install the toolchain:

sudo apt update
sudo apt install zfsutils-linux

Once the install finishes, confirm the kernel module is loaded with lsmod | grep zfs. If it returns nothing, run sudo modprobe zfs and try again. A successful load prints lines mentioning spl, zcommon, znvpair, zlua, zavl, zunicode, and zfs itself.

Before you touch any disks, double-check which devices are which. Australian retailers often ship external USB drives labelled in a way that disagrees with what lsblk reports, particularly when docks from the same brand share a product line. Run lsblk -d -o name,size,model,serial and write down the serial numbers of the drives you intend to dedicate to ZFS. It sounds paranoid until you accidentally overwrite a backup drive at 2 a.m. and lose a year of work.

A second preparation step is the clock. ZFS uses the system clock for timestamps, and a pool imported on a machine with the wrong time can produce confusing behaviour. Confirm with timedatectl that your timezone shows something like Australia/Sydney or Australia/Perth. If you dual-boot with Windows, disable Windows' "set time automatically" option or set Ubuntu to read the hardware clock as UTC, otherwise each reboot will roll the clock back by ten or eleven hours.

Building your first pool

With disk identities confirmed and the module loaded, creating a pool is a single command. For a mirrored pair of drives, where every block is stored twice so a single disk failure does not lose data, the syntax is:

sudo zpool create datapool mirror \
  /dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_S6PXNG0R123456 \
  /dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_S6PXNG0R789012

Replace the long identifiers with your own by-id paths. Avoid using /dev/sda-style names because they can shift between boots, especially when a new NVMe drive gets plugged in.

Once zpool create returns, the pool is mounted automatically at /datapool. Confirm with zpool status and df -h /datapool. To get sensible defaults like compression and atime disabled on the root dataset, set a few properties:

sudo zfs set compression=lz4 datapool
sudo zfs set atime=off datapool
sudo zfs set xattr=sa datapool
sudo zfs set acltype=posixacl datapool

The compression=lz4 setting is widely treated as the sweet spot: nearly free on modern CPUs and routinely shrinks photographs, music, and project files by five to fifteen percent. On a typical home machine in Melbourne or Adelaide, that compression alone pays back the time spent installing ZFS within a few months of normal use.

If you want to expose the pool over the network, create datasets for specific shares rather than dumping everything into the root. sudo zfs create datapool/media and sudo zfs create datapool/documents give you separate mountpoints under /datapool/media and /datapool/documents, each inheriting the same compression policy. Samba or NFS shares can then target those subpaths instead of locking down the entire pool.

Snapshots, clones, and recovering from mistakes

Snapshots are the feature that changes how people use their storage. A snapshot is a read-only view of a dataset at a specific moment, kept alongside the live data without consuming extra space initially. The zfs snapshot command is fast enough to run from a cron job every fifteen minutes.

A useful pattern is to automate snapshots using the sanoid and syncoid tools from the sanoid package, which keep, for example, twenty-four hourly snapshots, seven daily, and four weekly. Install it from the Ubuntu archive with sudo apt install sanoid, then enable the timer with sudo systemctl enable --now sanoid.timer. After a week you will have a rolling timeline of your data you can browse freely without scheduling anything yourself.

To roll a dataset back when something goes wrong, list snapshots first:

sudo zfs list -t snapshot -r datapool/documents

Then restore the one you want:

sudo zfs rollback datapool/documents@autosnap_2025-08-15_18-00-00

Because snapshots and clones are kept cheap, you can also experiment without risk. Cloning a snapshot gives you a writable copy that initially shares all of its blocks with the parent. A common Australian home-server workflow is to snapshot the configuration dataset before running an unattended upgrade, then clone it to test the new release on a separate path, and only promote the working clone once everything boots cleanly.

For backups, zfs send and zfs receive stream a dataset to another pool, file, or remote machine over SSH. A weekly zfs send datapool/documents@snapshot | ssh backup-host "zfs recv backuppool/documents" is enough to give an offsite copy. Many small businesses in regional towns around Townsville or Warrnambool rely on this pattern because it survives the kind of intermittent rural internet connections common outside the capitals: the stream can be resumed with zfs send -t, picking up where it left off.

Keeping the pool healthy over time

A pool that has been built does not stay healthy by itself. The single most important habit is running a scrub regularly, which reads every block, verifies its checksum, and repairs damaged blocks from parity when the topology allows. ZFS schedules a scrub automatically, but it is worth confirming the cadence.

sudo zpool status

The output's scan: line shows when the last scrub ran and whether any errors were found. To run one manually, use sudo zpool scrub datapool. Scrubs are I/O intensive, so scheduling them overnight or during off-peak NBN upload windows keeps them from stepping on interactive work. For a Synology-style box sitting in a Perth garage during a 38-degree summer afternoon, scrub timing is less critical than making sure the case fans are clean and the pool still has at least one degree of redundancy.

Other maintenance tasks are short. sudo zpool trim datapool tells SSDs to reclaim unused blocks, useful on NVMe pools where the drives otherwise lose performance over time. sudo zfs list -o space shows how much of the pool's space is consumed by snapshots, which can grow surprisingly large when long-running datasets are snapshotted frequently. The fix is to prune old snapshots with sudo zfs destroy datapool/documents@autosnap_2025-01-12_03-00-00, or to set retention through sanoid.

If a drive does fail, replacing it is straightforward. Identify the failed device with zpool status, physically swap the disk, find its new by-id path, then run sudo zpool replace datapool /dev/disk/by-id/old-faulty-id /dev/disk/by-id/new-id. The pool begins resilvering immediately and the filesystem stays available throughout, with a brief performance dip while the new mirror is rebuilt. A typical 1 TB consumer SSD resilvers in well under an hour on a recent machine, fast enough that scheduled backups overlap with the rebuild only briefly.

The next concrete step is to create one ZFS dataset on a spare drive today, copy a folder you care about into it, and snapshot it before making any system change.