For the complete documentation index, see llms.txt. This page is also available as Markdown.

28.7 ZFS Delegated Administration

ZFS provides a comprehensive permission delegation system that allows non-privileged users to perform ZFS administration operations.

For example, if each user's home directory is a dataset, users need permission to create and destroy snapshots of their home directory. A user performing backups can be granted permission to use the replication feature.

ZFS also allows the use of statistical scripts that only access space usage data for all users. The ability to delegate permissions can itself be delegated. Permission delegation applies to each subcommand and most properties.

User-Level ZFS Administration

ZFS delegation provides fine-grained permission control, allowing system administrators to grant specific ZFS administration permissions to non-privileged users. Since FreeBSD 14.1, adduser automatically creates separate datasets for non-privileged users' ZFS home directories and supports encryption.

This change (commit 516009ce8d38) makes adduser(8) automatically create a separate ZFS dataset for the user when the parent directory of the user's home directory is a ZFS dataset, for example /home/xxx inherits from /home. The -Z parameter of adduser can disable this behavior, and it also supports enabling encryption for non-privileged users' ZFS home directories.

Basic User-Level ZFS Administration

Take non-privileged users' ZFS datasets as an example. Two regular users, aria2 and safreya, were manually created during system installation.

List all ZFS file systems and their properties in the system:

% zfs list
NAME                                           USED  AVAIL  REFER  MOUNTPOINT
zroot                                         53.7G   396G    96K  /zroot
zroot/ROOT                                    12.8G   396G    96K  none
zroot/ROOT/14.1-RELEASE-p3_2024-09-17_194642     8K   396G  11.6G  /
zroot/ROOT/default                            12.8G   396G  11.9G  /
zroot/aria2                                    187M   396G   187M  /usr/local/data/aria2
zroot/home                                    7.74G   396G    96K  /home
zroot/home/aria2                               128K   396G   128K  /home/aria2   # Note this line
zroot/home/safreya                            7.74G   396G  7.70G  /home/safreya # Note this line
zroot/jails                                   3.12G   396G  3.12G  /usr/jails
zroot/sec                                     28.5G   396G  28.5G  /usr/local/data/sec
zroot/tmp                                      102M   396G   102M  /tmp
zroot/usr                                     1.34G   396G    96K  /usr
zroot/usr/ports                               1.34G   396G  1.34G  /usr/ports
zroot/usr/src                                   96K   396G    96K  /usr/src
zroot/var                                     1.58M   396G    96K  /var
zroot/var/audit                                 96K   396G    96K  /var/audit
zroot/var/crash                                 96K   396G    96K  /var/crash
zroot/var/log                                 1.02M   396G  1.02M  /var/log
zroot/var/mail                                 168K   396G   168K  /var/mail
zroot/var/tmp                                  120K   396G   120K  /var/tmp

Among them:

That is, when creating users, the system has already created separate datasets zroot/home/aria2 and zroot/home/safreya for users aria2 and safreya respectively.

Next, check the user permissions on both datasets.

From the output, it can be seen that when creating users, the system grants four permissions — create, destroy, mount, and snapshot — to their datasets by default.

ZFS delegation permissions are stored in the dataset's metadata. Local+Descendent permissions indicates that the permission setting applies to both the current dataset and its scope covers child datasets as well.

zfs allow <user> allow <dataset> grants the specified user the ability to delegate any permissions they possess to other users on the target dataset or its child datasets. If a user has the snapshot permission and the allow permission, that user can grant the snapshot permission to other users.

Therefore, for these two datasets, regular users can also use the snapshot feature:

Now let's look at the create, destroy, and mount permissions:

Creating a new dataset involves mounting, which requires setting FreeBSD's sysctl vfs.usermount to 1 to allow non-root users to mount file systems.

From the output, it can be seen that the create and destroy permissions work correctly. To prevent abuse, there is another restriction: non-root users must own the mount point to mount a file system.

At this point, the basic functionality of user-level ZFS administration is ready. However, the rollback permission is not available by default and must be granted separately by the root user.

Roll back the zroot/home/safreya file system to the snap1 snapshot state:

Grant user safreya permission to perform rollback operations on the zroot/home/safreya file system as the root user:

User-Level ZFS Encryption

In FreeBSD 14.1, to use ZFS encryption at the user level, specific permissions must be granted to the user.

Grant user safreya permission to perform key management and encryption operations on the zroot/home/safreya file system:

Display the current permission delegation settings for the zroot/home/safreya file system:

The five permission properties — change-key, load-key, keyformat, keylocation, and encryption — are used for ZFS encryption functionality.

Create a ZFS dataset zroot/home/safreya/secret with encryption enabled, using a passphrase as the key format:

Check the encryption status:

Check the mounted property; the encrypted dataset is mounted upon creation. Now create a file, then unmount the encrypted dataset:

When unmounting an encrypted dataset, its key must also be unloaded; when mounting the dataset, the key must be loaded first:

Warning

Because the destroy permission is granted to users by default, the destroy subcommand can successfully destroy a dataset regardless of whether it is mounted. Therefore, if the operator is not the user themselves, the dataset could still be deleted.

Delegation grants non-privileged users proxy permissions, giving them root-like privileges when operating on delegated datasets without requiring a password. Therefore, when granting permissions, the scope and permission properties should be reasonably restricted, such as disabling the destroy permission property.

Revoke user safreya's destroy permission on the zroot/home/safreya file system:

Display the current permission delegation settings for the zroot/home/safreya file system:

Here, zroot/home/safreya/secret is covered by the Local+Descendent permission scope on zroot/home/safreya. ZFS delegation permissions do not have an inheritance mechanism; permissions are stored on the dataset where they are granted, and Local+Descendent indicates that the permission scope covers both the dataset itself and its descendant datasets. When a permission is revoked on a parent dataset, its Descendent scope is also removed, and users on descendant datasets will lose the corresponding permission. If you need to control permissions on descendant datasets separately, you must explicitly grant or revoke permissions on the descendant datasets.

adduser and User Home Directory Encryption

The adduser command can directly use encrypted user home directory datasets, but the permissions granted by default are insufficient; after unmounting, non-privileged users cannot mount directly.

Display the current permission delegation settings for the zroot/home/test file system:

Unmount the dataset and key:

Switch to the regular user test and try to mount:

Permission denied indicates insufficient permissions; access is denied.

References

Last updated