ZFS

ZFS is an advanced filesystem.

ZPool

Create a pool*

zpool create -f -m <mount> <pool> [raidz(2|3)|mirror] <ids>

Pool Status

zpool list
zpool status -v

Import Pool

zpool import -l -d /dev/disk/by-id <pool> # Import pool
zpool import -a # Import all available pools
zpool import -a -f # Import all available pools with force option

Export Pool

zpool export <pool>

Extend Pool

zpool add <pool> <device-id>

Destroy pool / dataset

zpool destroy <pool>
zfs destroy <pool>/<dataset>

Rename a pool

zpool export oldname
zpool import oldname newname

Upgrade pool

zpool upgrade <pool>

Automount

Specify this for zfs-import-cache.service to pick up the pool

zpool set cachefile=/etc/zfs/zpool.cache <pool>

Datasets

Dataset Managment

Create Dataset

zfs create <nameofzpool>/<nameofdataset>

Create encrypted dataset:

openssl rand 32 > /path/to/key # Generate key
 
zfs create -o encryption=on -o keyformat=raw -o keylocation=file://$KEYLOCATION "$DATASET"

Change encryption keys:

zfs change-key -l [-o keylocation=value] [-o keyformat=value] [-o pbkdf2iters=value] filesystem

Load all encryption keys

zfs load-key -a

Load all keys at boot with systemd /etc/systemd/system/zfs-load-key.service:

[Unit]
Description=Load encryption keys
DefaultDependencies=no
After=zfs-import.target
Before=zfs-mount.service
 
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/zfs load-key -a
StandardInput=tty-force
 
[Install]
WantedBy=zfs-mount.service

Destroy dataset:

# Destroy dataset
zfs destroy <pool>/<dataset>
 
# Destroy Dataset recursively with all subdatasets
zfs destroy -r <pool>/<dataset>

Mount dataset:

zfs mount <pool>/<dataset>
zfs unmount <pool>/<dataset>

Snapshots

Create snapshot:

zfs snapshot <pool>/<dataset>@<snapshot>

Rollback snapshot:

# Rollback to snapshot and destroy any newer snapshots
zfs rollback -r <pool>/<dataset>@<snapshot>

Show differences between snapshots:

zfs diff -F tank/test@before tank/test

The -F flag shows more information about the type of files that have changed:

SymbolMeaning
BBlock device
CCharacter device
/Directory
>Door
``
@Symbolic link
PEvent port
=Socket
FRegular file

Send and receive:

zfs send -v -w <pool>/<dataset>@<snapshot> | zfs recv <pool>/<newdataset>

Properties

Get properties:

zfs get <property> <pool>/<dataset>

Set properties

zfs set <property>=<value> <pool>/<dataset>

Available Properties

PROPERTYEDITINHERITVALUES
availableNONO<size>
clonesNONO<dataset>[,...]
compressratioNONO<1.00x or higher if compressed>
createtxgNONO<uint64>
creationNONO<date>
encryptionrootNONO<filesystem | volume>
filesystem_countNONO<count>
guidNONO<uint64>
keystatusNONOnone / unavailable / available
logicalreferencedNONO<size>
logicalusedNONO<size>
mountedNONOyes / no
originNONO<snapshot>
redact_snapsNONO<snapshot>[,...]
referencedNONO<size>
snapshot_countNONO<count>
typeNONOfilesystem / volume / snapshot / bookmark
usedNONO<size>
usedbychildrenNONO<size>
usedbydatasetNONO<size>
usedbyrefreservationNONO<size>
usedbysnapshotsNONO<size>
writtenNONO<size>
atimeYESYESon / off
casesensitivityNOYESsensitive / insensitive / mixed
checksumYESYESon / off / fletcher2 / fletcher4 / sha256 / sha512 / skein / edonr / blake3
compressionYESYESon / off / lzjb / gzip / gzip-[1-9] / zle / lz4 / zstd / zstd-[1-19] / zstd-fast / zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]
copiesYESYES1 / 2 / 3
dedupYESYESon / off / verify / sha256[,verify] / sha512[,verify] / skein[,verify] / edonr,verify / blake3[,verify]
encryptionNOYESon / off / aes-128-ccm / aes-192-ccm / aes-256-ccm / aes-128-gcm / aes-192-gcm / aes-256-gcm
keyformatNONOnone / raw / hex / passphrase
keylocationYESNOprompt / <file URI> / <https URL> / <http URL>
mountpointYESYES<path> / legacy / none
pbkdf2itersNONO<iters>
quotaYESNO<size> / none
readonlyYESYESon / off
relatimeYESYESon / off
reservationYESNO<size> / none
snapdirYESYEShidden / visible

Scrub

Like Btrfs ZFS can heal itself with scrubbing

Start a scrub:

zpool scrub <pool>

Cancel a scrub:

zpool scrub -s <pool>

Autoscrubbing with systemd:

/etc/systemd/system/zfs-scrub@.timer

[Unit]
Description=Monthly zpool scrub on %i
 
[Timer]
OnCalendar=monthly
AccuracySec=1h
Persistent=true
 
[Install]
WantedBy=multi-user.target

/etc/systemd/system/zfs-scrub@.service

[Unit]
Description=zpool scrub on %i
 
[Service]
Nice=19
IOSchedulingClass=idle
KillSignal=SIGINT
ExecStart=/usr/bin/zpool scrub %i
 
[Install]
WantedBy=multi-user.target