OpenZFS

OpenZFS, formerly ZFS on Linux, is a project aimed at bringing the ZFS file system to the Linux kernel.

If using a BSD, ZFS should be supported out of the box.


Installation

Arch

The first step is almost always downgrading the kernel.

version="major.minor.patch-release"
pacman -U https://archive.archlinux.org/packages/l/linux-lts/linux-lts-$version-x86_64.pkg.tar.zst https://archive.archlinux.org/packages/l/linux-lts-headers/linux-lts-headers-$version-x86_64.pkg.tar.zst
mkinitcpio -P
grub-mkconfig -o /boot/grub/grub.cfg

To determine which kernel version is supported, try installing ZFS from the unofficial repository.

pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76
echo "[archzfs]\nServer = https://archzfs.com/$repo/$arch\n" >> /etc/pacman.conf
pacman -Syu archzfs-linux

If the last command gives an error about an unsatisfiable dependency involving the kernel, the indicated version is what to use in the above snippet.

With a supported kernel and the ZFS module installed, try booting.


Pools

The lowest level of ZFS is pools.

Identify disks by their IDs like:

$ ls -lh /dev/disk/by-id/
total 0
lrwxrwxrwx 1 root root 1 Jan 01 12:30 ata-ABCDE
lrwxrwxrwx 1 root root 1 Jan 01 12:30 ata-FGHIJ
lrwxrwxrwx 1 root root 1 Jan 01 12:30 ata-KLMNO
lrwxrwxrwx 1 root root 1 Jan 01 12:30 ata-PQRST

With these 4 drives of N GB storage each, create a RAIDz2 pool where 2N GB will be dedicated to parity rather than storage. The pool will be fault tolerant for up to 2 failed drives.

zpool create -f tank raidz2 ata-ABCDE ata-FGHIJ ata-KLMNO ata-PQRST

Alternatively create a RAIDz1 pool where just N GB will be dedicated to parity (but the pool will only be fault tolerant of 1 drive failure).

Alternatively alternatively, create a Mirror pool to maximize fault tolerance (up to 3 failed drives) but leaving just N GB of storage.

Pools can be created with encryption, but it is not recommended. A pool's encryption setting is inherited, so the pool is permanently locked to this singular cryptographic algorithm.

The pool will be mounted to a root-level directory named after the pool (/tank in this case).

Check the status of pools with zpool status.

To ensure that the pools mount at boot, try:

systemctl enable zfs-import-cache.service zfs.target zfs-import.target


Datasets

To create a dataset within a pool, try:

zfs create tank/data

To create an encrypted dataset, try:

zfs create -o encryption=on -o keyformat=passphrase tank/enc

The default cryptographic algorithm is aes-256-gcm.

To mount an encrypted dataset, try:

zfs load-key tank/enc
zfs mount tank/enc


Snapshots

To create a snapshot of a pool, try:

zfs snapshot tank/data@snap1

At initialization, a snapshot has negligible size. It grows as changes are made in the dataset.

To delete a snapshot, try:

zfs destroy pool/dataset@snap1

If @snap1 is omitted from the zfs-destroy call, the dataset will be destroyed instead.

To delete a range of snapshots, try:

zfs destroy pool/dataset@snap1%snap9

snap1 and snap9 can be omitted to delete an open range of snapshots, i.e. to delete snap9 and all older snapshots, or to delete snap1 and all newer snapshots.

To list available snapshots, try:

zfs list -t snapshot

Sending and Receiving

A snapshot can be copied from one dataset to another like:

zfs send tank1/data@snap1 | zfs recv tank2/data

Note that the canonical name for recv is zfs-receive(8).

Alternatively, a snapshot can be compressed and written to a remote filesystem like:

zfs send tank/data@snap1 | gzip | ssh user@host "cat > dest.tar.gz"

Note furthermore the -R flag for zfs-send(8), which create a replicate send. This bundles all children datasets (recursively), all snapshots, and all configurations.

Incremental Sending and Receiving

The actual utility of these tools is incremental sends:

zfs send -i tank1/data@snap1 tank1/data@snap2 | zfs recv tank2/data

If there are multiple snapshots between @snap1 and @snap2, note that using -I tank1/data@snap1 on one call is equivalent to the series of calls using i tank1/data@snap1a; i tank1/data@snap1b; and so on.

Note furthermore that the -F flag on zfs-receive(8) causes a roll-back to the most recent snapshot of tank2/data before initiating the receive. Then, any snapshots that do not exist in tank1/data are deleted from tank2/data. This is mostly useful for incremental replicate sends (i.e., zfs send -R -i ...).

To estimate the size of an incremental send, use the dry-run flag (-n).

zfs send -n -i tank1/data@snap1 tank1/data@snap2


Administration

Consider disabling access times with zfs set atime=off tank (or zfs set atime=off tank/data to limit the setting to a dataset).

Consider enabling compression. Upstream considers this to be a reasonable default, even for uncompressible files.

zfs set compression=on tank

The default compression algorithm is lz4.

ZFS pools must be scrubbed to ensure that bit rot is addressed before backups are lost. To trigger this manually, try:

zpool scrub tank

Alternatively, enable a timer to automate this:

systemctl enable [email protected]


See also

zfs-create(8)

zfs-destroy(8)

zfs-list(8)

zfs-mount(8)

ifs-receive(8)

zfs-send(8)

zfs-snapshot(8)

zpool-create(8)

zpool-scrub(8)

zpool-status(8)


CategoryRicottone