Example desktop filesys layout

Howdy, I’ve heard that it’s not a great idea to stick everything in a single pool. Also, I once did a trial install of Ubuntu back when ZFS was an option and I seem to remember it created a thousand pools.

I’ve looked around, but haven’t seen this type of elementary topic documented. Does anyone have any links handy?

First, some terminology—and I found this very confusing when I started with ZFS. The pool is made up of vdevs (the physical grouping of disks) and it houses datasets of various types. So substitute ‘dataset’ in place of ‘pool’ in your question.

Basically, you want a separate dataset for any boundary where you need different properties (like maybe you want some parts encrypted or a different block size for database storage or you want to take backups on a different schedule). For a desktop machine, I think the most important thing is to have the /home directory and all of its subdirectories be separate datasets. That would make it trivial to keep really frequent backups of your user’s data without storing the whole operating system.

One great place to get a perspective on desktop-focused dataset structure would be the zfsbootmenu guide: Debian (UEFI) — ZFSBootMenu 3.0.1 documentation

That early zsys setup was a nightmare. Just because you can create a dataset for every little thing doesn’t mean you should do it …

I’ve found simple partitioning works well

  • pool/ROOT : container for root filesystems
  • pool/ROOT/noble : root filesystem for Ubuntu 24.04/noble
  • pool/home : container for home dirs
  • pool/home/root : root home dir
  • pool/home/alice : user home dir
  • pool/docker : for docker mounted at /var/lib/docker
  • pool/virtualbox : for Virtualbox VMs - mounted at /Virtualbox and usually with a symlink in ~/Virtualbox for me

etc.

Understood. Thanks.

I get the picture now. Thanks.

A few months ago, I used the installer for Ubuntu 25.04 (as a basis for my Kubuntu with root-on-OpenZFS). Here’s the filesystems layout of the two pools that were produced by the installer:

grahamperrin@mowa219-gjp4 ~> zfs list -t fs -o name,mountpoint,canmount -r bpool
NAME                      MOUNTPOINT  CANMOUNT
bpool                     /boot       off
bpool/BOOT                none        off
bpool/BOOT/ubuntu_v0hpws  /boot       on
grahamperrin@mowa219-gjp4 ~> zfs list -t fs -o name,mountpoint,canmount -r rpool
NAME                                              MOUNTPOINT                CANMOUNT
rpool                                             /                         off
rpool/ROOT                                        none                      off
rpool/ROOT/ubuntu_v0hpws                          /                         on
rpool/ROOT/ubuntu_v0hpws/srv                      /srv                      on
rpool/ROOT/ubuntu_v0hpws/usr                      /usr                      off
rpool/ROOT/ubuntu_v0hpws/usr/local                /usr/local                on
rpool/ROOT/ubuntu_v0hpws/var                      /var                      off
rpool/ROOT/ubuntu_v0hpws/var/games                /var/games                on
rpool/ROOT/ubuntu_v0hpws/var/lib                  /var/lib                  on
rpool/ROOT/ubuntu_v0hpws/var/lib/AccountsService  /var/lib/AccountsService  on
rpool/ROOT/ubuntu_v0hpws/var/lib/NetworkManager   /var/lib/NetworkManager   on
rpool/ROOT/ubuntu_v0hpws/var/lib/apt              /var/lib/apt              on
rpool/ROOT/ubuntu_v0hpws/var/lib/dpkg             /var/lib/dpkg             on
rpool/ROOT/ubuntu_v0hpws/var/log                  /var/log                  on
rpool/ROOT/ubuntu_v0hpws/var/mail                 /var/mail                 on
rpool/ROOT/ubuntu_v0hpws/var/snap                 /var/snap                 on
rpool/ROOT/ubuntu_v0hpws/var/spool                /var/spool                on
rpool/ROOT/ubuntu_v0hpws/var/www                  /var/www                  on
rpool/USERDATA                                    none                      off
rpool/USERDATA/home_dz7uxs                        /home                     on
rpool/USERDATA/root_dz7uxs                        /root                     on
rpool/var                                         /var                      off
rpool/var/lib                                     /var/lib                  off
rpool/var/lib/docker                              /var/lib/docker           on
grahamperrin@mowa219-gjp4 ~> 

at risk of necro-bumping, but can’t help but insert an opinion:

Apparently Ubuntu uses a separate boot pool because they insist on using GRUB (grub’s support of zfs is old, and from what I’ve read, partly broken). If you can get away from GRUB (I’d suspect you’d thank yourself at some point), then no need to complicate things by creating 2 pools.

I read or heard somewhere, a comment about mountpoints. This person (whoever it was, can’t remember) said it was much easier to create your datasets in the hierarchy of the mountpoints, that way the mountpoints don’t have to be manually altered/managed/maintained; they will just be correct by inheriting the relative paths from the one, top level dataset.

This Ubuntu example from @grahamperrin mostly demonstrates that, though there are some deviations.

1 Like

In the Year of Our Lord 2026 I can’t figure out why people still put up with it. Invariably I’ll rip it out of my machines and never look back.

I’m wondering about this myself. What challenges me is having intermediate “placeholder” datasets where there’s no desire to apply unique snapshot policy or dataset properties.

path zstuff desire
/ tank/ROOT/fedora broad “system” snapshot strategy
/home tank/ROOT/fedora/home [IDGAF]
/home/user/ tank/ROOT/fedora/home/user apply unique snapshot strategy

Do I use this “placeholder” dataset at /home to preserve the hierarchy and facilitate property inheritance? Or eliminate it and simply create (for example) tank/ROOT/fedora/home_user and manually set the mountpoint?

This is the most basic example. Now consider a desire for special props on a seven-deep directory. Do I create six placeholder datasets? Or perhaps make the tail wag the dog by relocating that directory closer to the top?

On one hand I see benefit from interacting with fewer “touch points” toward the top and letting inheritance do the work.

On the other, did it really save work when this stuff is scriptable/manageable through playbooks (among other things)? To change something near the top of the hierarchy and NOT have it flow down the tree I’ll need to disable inheritance somewhere. But where is inheritance turned on and where isn’t it for any given property? More touch points to check.

I might be missing something [in addition to a brain]…

:thinking:

You’d only need to create six placeholder datasets if you intended to actually have six separate policy definitions along the way.

Let’s say we’re talking about /usr/local/lib/x86_64-linux-gnu/perl/5.34.0/auto/YAML.

Maybe you want to set compress=gzip on that specific folder, because it’s all YAML, therefore plain human-readable text, therefore super compressible with gzip. But you certainly don’t want everything along the way gzip compressed.

Let’s also say you maybe want a different set of policies for /usr than you have for /.

So you’d have three datasets:

poolname/ROOT/ubuntu -- mounted on / (mountpoint explicitly set)
poolname/ROOT/ubuntu/usr -- mounted on /usr (inherited)
poolname/ROOT/ubuntu/usr/perl-5.34.0-auto-YAML -- mounted on /usr/llocal/lib/x86_64-linux-gnu/perl/5.34.0/auto/YAML (mountpoint explicitly set)

/usr/local/lib, and all the intermediate folders as far as /usr/local/lib/x86_64-linux-gnu/perl/5.34.0/auto, would simply be normal folders inside the poolname/ROOT/ubuntu/usr dataset, if they don’t need any special properties of their own.

This isn’t the only way to manage things, but it’s the most sensible answer to your hypothetical question, IMO. You certainly could create shitloads of intermediate datasets, but I typically wouldn’t recommend it when there are that many intermediate directories.

Now, in the case of home folders… yeah, I have a parent dataset for /home as well as child datasets for /home/username1 and /home/username2, and I let the actual home folders inherit their mountpoint from the dataset mounted on /home.

Ultimately, you just need to organize things in a way that makes sense–hopefully to most any arbitrary relatively bright person as well as yourself–because the computer itself doesn’t give a rats ass how you organized it or even if you organized it. This is all about being able to recognize and maintain your own work.

LOL, I see what you did there… What you say makes perfect sense.

Follow-on question… What’s the best method to prune/graft a dataset topology? Create a new dataset in the desired location then zfs send the data across?

Or zfs clone to the desired location then zfs promote to break source dependency?

Something else?

I’m not sure what you mean by this, can you clarify?

Let’s say I’ve got a nested “tree” of datasets that I’d prefer to flatten.

Or I don’t like the tree I have now and want I to move datasets around, creating a redesigned hierarchy.

I presume we can’t just alter an existing hierarchy via dataset renames… Or can we?

Note I’m not talking about mountpoints – I know can set those to anything I want. I refer to the dataset “tree” itself.

Oh, yes, you absolutely can. zfs rename pool/parent/child pool/child results not only in “moving” pool/parent/child to pool/child, it also “moves” pool/parent/child/grandchild to pool/child/grandchild.

1 Like