Disko-ZFS: Declaratively Managing ZFS Datasets (opens in new tab)

Published on Jan 23, 2026

The work on disko-zfs was carried out under contract with Numtide. Thank you Numtide for making this project a reality!

If you’re at least somewhat like me, then you use ZFS almost religiously. Every server, every laptop, every appliance (excluding those that really could not run ZFS due to memory constraints or fragile flash storage) runs ZFS. You run ZFS even if you don’t use mirrors, stripes, or any kind of special vdevs. You run ZFS because you want to, because having snapshots, datasets and compression makes the device feel familiar and welcoming. If that’s at least somewhat you, you will appreciate the tool I have for you in store today.

Too Many Datasets

Given a situation where a ZFS pool has just too many datasets for you to comfortably manage, or perhaps you have a few datasets, but you just learned of a property that you really should have set from the start, what do you do? Well, I don’t know what you do, I would love to hear about that, so please do reach out to me, over Matrix preferably.

In any case, what I came up with is disko-zfs. A simple Rust program that will declaratively manage datasets on a zpool. It does this based on a JSON specification, which lists the datasets, their properties and a few pieces of extra information.

disko-zfs is safe

disko-zfs will never ever destroy any datasets, it will merely say what datasets it would delete, if it could destroy datasets. But it cannot destroy datasets. The internal enumeration representing what actions it should take does not even support that action. You can verify that yourself by clicking here. ZfsAction is used to create commands that will be executed, DestructiveAction is used to generate only informative commands that are never executed.

The Schema

Listing 1: A production specification from one of Numtide’s machines

{
"datasets": {
"zroot": {
"properties": {
"atime": "off",
"com.sun:auto-snapshot": "false",
"compression": "zstd-2",
"dnodesize": "auto",
"mountpoint": "none",
"recordsize": "128K",
"xattr": "on"
}
},
...
"zroot/ds1/persist/var/lib/forgejo": {
"properties": {
"mountpoint": "legacy"
}
},
"zroot/ds1/persist/var/lib/postgresql": {
"properties": {
"mountpoint": "legacy",
"recordsize": "8k"
}
},
...
},
"ignoredDatasets": [
"zroot/ds1/root/*"
],
"ignoredProperties": [
"nixos:shutdown-time",
":generation",
"com.sun:auto-snapshot"
],
"logLevel": "info"
}

As you can see, it’s relatively self explanatory. The information that this JSON format carries is:

Loading more...

Keyboard Shortcuts

Navigation
Next / previous item
j/k
Open post
oorEnter
Preview post
v
Post Actions
Love post
a
Like post
l
Dislike post
d
Undo reaction
u
Save / unsave
s
Recommendations
Add interest / feed
Enter
Not interested
x
Go to
Home
gh
Interests
gi
Feeds
gf
Likes
gl
History
gy
Changelog
gc
Settings
gs
Browse
gb
Search
/
General
Show this help
?
Submit feedback
!
Close modal / unfocus
Esc

Press ? anytime to show this help