Create the zpool
on top of the system-pool
logical volume.
sudo zpool create -f \
-o ashift=12 \
-O acltype=posixacl \
-O atime=on \
-O compression=on
-O com.sun:auto-snapshot=true \
-O dnodesize=auto \
-O normalization=formD
-O mountpoint=none \
-O relatime=on \
-O xattr=sa \
<zpool name> \
<target partition>
zpool list
The ashift=12
corresponds to a system with native sector size of 4096 bytes;
consult the OpenZFS documentation on Advanced Format
Disks
for more information about this parameter.
Unfortunately I'm not aware of any way to check which value works best here on Linux; some reading online turned up this whitepaper from Intel, which suggests that "most new HDDs and Intel SSDs perform better with a [4KiB] alignment".
See this entry in the Arch Wiki for a few more crumbs of detail (but not much more than that).
acltype=posixacl
enables the use of POSIX access control levels stored as
"extended attributes", and xattr=sa
tells ZFS to store these attributes in the
file inode rather a hidden subdirectory (as is the default with xattr=on
).
See this r/zfs comment for details.
ZFS will track file access time when atime=on
is set, however the default
setting can be I/O intensive; relatime=on
applies the atime
semantics from
the EXT4/XFS filesystems to ZFS as a compromise.
See the Arch Wiki ZFS Tuning section for details.
ZFS has a compression=on
option which selects one of either the lzjb
or
lz4
algorithms (depending on whether the lz4_compress
feature flag is
enabled).
It's worth keeping an eye on zstd
compression, which landed in OpenZFS 2.0,
although at the time of writing it's too new for me to consider here.
This flag controls ZFS' auto-snapshotting functionality; by default, if this is not set, the system will not auto-snapshot even if the NixOS module is enabled.
I chose to enable this at the pool-level since I want snapshotting to be opt-out on a per-dataset level (rather than opt-in).
ZFS can automatically determine the
dnode
size with
dnodesize=auto
; this is especially useful in concert with the xattr=sa
property.
Most guides I've seen suggest setting mountpoint=none
on the zpool
. This
setting ensures that the given ZFS construct may not be mounted by the operating
system, and should be managed/used entirely by ZFS.
ZFS doesn't enforce that filenames must be UTF-8 by default;
normalization=formD
enables this, at the expense of breaking compatibility
with anything which may expect a filename that is not valid UTF-8 text.
See this post for details.
Create a ZFS dataset for the Nix store, and mount it.
sudo zfs create -p \
-o atime=off \
-o mountpoint=legacy \
-o com.sun:auto-snapshot=false \
<zpool name>/nix
sudo zfs snapshot <zpool name>/nix@pristine
Unlike the zpool, atime
will be disabled here since the Nix store doesn't need
to track file access time at all.
Since Nix manages the store entirely on its own, it shouldn't be necessary to enable automatic snapshotting so that can be turned off as well.
Finally, it can be helpful to manually take a "pristine" snapshot of the data before anything files are written.