rss logo

How to Install and Use ZFS on Debian

OpenZFS logo

Introduction

ZFS is an open-source file system combined with a logical volume manager, designed to provide high data integrity, scalability, and advanced storage features. It is licensed under the Common Development and Distribution License (CDDL).

Originally developed by Sun Microsystems and led by Jeff Bonwick, ZFS is now maintained by the OpenZFS community.

Key Features

  • High storage capacity: supports very large storage pools and filesystems.
  • Integrated volume management: combines filesystem and volume manager in a single solution.
  • Data integrity: end-to-end checksumming with automatic error detection and self-healing.
  • Snapshots and clones: fast, space-efficient backups and easy data replication.
  • Deduplication: eliminates duplicate data blocks to save space (use with caution).
  • Compression: transparent compression (lz4, zstd) to improve storage efficiency and performance.

Installation

On Debian, ZFS can be installed from the official repositories. Make sure the contrib repository is enabled, then install the required package:

root@host:~# apt update && apt install zfsutils-linux

For detailed and up-to-date instructions, refer to the official OpenZFS documentation: https://openzfs.github.io/openzfs-docs

ZFS Commands

This section provides common ZFS commands for creating, managing, and monitoring storage pools.

Create a ZFS Pool

  • List available disk IDs:
root@host:~# ls -lah /dev/disk/by-id/
  • Create a mount point:
root@host:~# mkdir /zfs

🚨 Warning: RAID 0 (stripe) provides no redundancy. Data will be lost if a single disk fails.

  • Create a storage pool (RAID 0 / stripe):
root@host:~# zpool create -f -o ashift=12 -m /zfs pool01 stripe \
scsi-SATA_WDC_WD20EARS-07_WD-WCAZA796741 \
scsi-SATA_WDC_WD20EARS-07_WD-WCAZB7569258 \
scsi-SATA_WDC_WD20EARS-07_WD-WCPZB7464217
  • zpool create: create a new storage pool
  • -f: force creation (use with caution)
  • -o ashift=12: optimize alignment for modern disks (4K sectors)
  • -m: set mount point (default is /)
  • pool01: pool name
  • stripe: RAID 0 (no redundancy)
  • disk IDs: devices from /dev/disk/by-id/
  • Add a hot spare disk:
root@host:~# zpool add pool01 spare /dev/sdX
  • List available pools:
root@host:~# zpool list
  • Display pool history:
root@host:~# zpool history pool01
  • Change mount point:
root@host:~# zfs set mountpoint=/zfs pool01
  • If the pool does not mount on a new system:
root@host:~# zpool export pool01
root@host:~# zpool import -a
  • Or force import:
root@host:~# zpool import -f pool01
  • Disable atime (recommended for performance):
root@host:~# zfs set atime=off pool01
  • Enable lz4 compression (recommended):
root@host:~# zfs set compression=lz4 <pool>
  • Enable zstd compression (higher compression ratio, more CPU usage):
root@host:~# zfs set compression=zstd <pool>
  • Destroy a storage pool:

🚨 Warning: This command permanently destroys all data stored in the pool.

root@host:~# zpool destroy <pool>

Maintenance

Filesystem Check (Scrubbing)

Note: ZFS does not use traditional filesystem checks like fsck. Instead, it uses a process called scrubbing to verify and repair data integrity.

  • Run a scrub (data integrity check):
root@host:~# zpool scrub pool01
  • Check scrub status and pool health:
root@host:~# zpool status
  • Clear errors from the pool status:
root@host:~# zpool clear pool01

Display Properties

  • List all ZFS properties:
root@host:~# zfs get all <pool>

Replace a Failed Drive

  • Replace a disk in a pool:
root@host:~# zpool replace pool01 <old_disk> <new_disk>

Monitoring

  • Display all pool properties:
root@host:~# zpool get all pool01
  • Check pool status and device health:
root@host:~# zpool status -v pool01
  • Monitor I/O statistics:
root@host:~# zpool iostat <interval> <count>
root@host:~# zpool iostat 5 10

ZFS Encryption

💡 Note: Modern versions of ZFS support native encryption at the dataset level. This is generally preferred over external solutions like dm-crypt.

Encryption with dm-crypt (LUKS)

Encrypt disks

root@host:~# cryptsetup luksFormat /dev/sdb1
root@host:~# cryptsetup luksFormat /dev/sdc1
root@host:~# cryptsetup luksFormat /dev/sdd1

Open encrypted disks

root@host:~# cryptsetup luksOpen /dev/sdb1 zfs01
root@host:~# cryptsetup luksOpen /dev/sdc1 zfs02
root@host:~# cryptsetup luksOpen /dev/sdd1 zfs03

Create ZFS pool on encrypted devices

root@host:~# zpool create -f -m /zfs pool01 mirror \
/dev/mapper/zfs01 \
/dev/mapper/zfs02

Native ZFS Encryption

💡 Note: Encryption in ZFS is applied at the dataset level, not at the pool level.

Create a ZFS pool

First, create a ZFS pool that will host the encrypted dataset.

root@host:~# zpool create -f -m /zfs pool01 /dev/sdX

Create an encrypted dataset

There are several ways to protect an encrypted dataset. The most common are passphrase and keyfile.

Passphrase
  • Create an encrypted dataset using a passphrase:
root@host:~# zfs create -o encryption=on -o keyformat=passphrase pool01/dataset01
Keyfile
  • Generate a secure keyfile:
root@host:~# head -c 32 /dev/urandom > /root/keyfile
root@host:~# chmod 600 /root/keyfile
  • Create an encrypted dataset using the keyfile:
root@host:~# zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///root/keyfile pool01/dataset01

Load and mount an encrypted dataset

After a reboot, or when accessing the pool on another system, you need to load the encryption key and mount the dataset. The following example shows how to mount a dataset protected with a keyfile.

  • Check configured key location:
root@host:~# zfs get keylocation pool01/dataset01
NAME              PROPERTY     VALUE                 SOURCE
pool01/dataset01  keylocation  file:///root/keyfile  local
  • Load the encryption key:
root@host:~# zfs load-key pool01/dataset01
  • Mount the dataset:
root@host:~# zfs mount pool01/dataset01

Source: OpenZFS documentation; linuxfr.org