> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-28-the-zfs-file-system/di-28.7-jie-zfs-wei-tuo-guan-li.md).

# 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:

```sh
% 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:

```sh
zroot/home/aria2                               128K   396G   128K  /home/aria2
zroot/home/safreya                            7.74G   396G  7.70G  /home/safreya
```

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.

```sh
% zfs allow zroot/home/aria2        # Display or set permission delegation for the zroot/home/aria2 file system
---- Permissions on zroot/home/aria2 ---------------------------------
Local+Descendent permissions:
        user aria2 create,destroy,mount,snapshot
safreya ~ % zfs allow zroot/home/safreya
---- Permissions on zroot/home/safreya -------------------------------
Local+Descendent permissions:
        user safreya create,destroy,mount,snapshot
```

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:

```sh
% zfs snapshot zroot/home/safreya@snap1   # Create snapshot snap1 for the zroot/home/safreya file system
% zfs list -t snap                        # List all ZFS snapshots
NAME                                       USED  AVAIL  REFER  MOUNTPOINT
zroot/home/safreya@snap1                     0B      -  7.70G  -
```

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

```sh
% zfs create zroot/home/safreya/dataset_1        # Create a new ZFS dataset dataset_1 under zroot/home/safreya
cannot mount 'zroot/home/safreya/dataset_1': Insufficient privileges
filesystem successfully created, but not mounted
```

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.

```sh
% su -m root -c 'sysctl vfs.usermount=1'
Password:
vfs.usermount: 0 -> 1
% zfs create zroot/home/safreya/dataset_2        # Create a new ZFS dataset dataset_2 under zroot/home/safreya
% zfs list        # List all ZFS file systems and their properties
NAME                                           USED  AVAIL  REFER  MOUNTPOINT

      ...some parts omitted...

zroot/home                                    7.79G   396G    96K  /home
zroot/home/aria2                               128K   396G   128K  /home/aria2
zroot/home/safreya                            7.79G   396G  7.68G  /home/safreya
zroot/home/safreya/dataset_1                    96K   396G    96K  /home/safreya/dataset_1
zroot/home/safreya/dataset_2                    96K   396G    96K  /home/safreya/dataset_2

      ...some parts omitted...
```

```sh
% zfs destroy zroot/home/safreya/dataset_1       # Delete ZFS dataset zroot/home/safreya/dataset_1
% zfs destroy zroot/home/safreya/dataset_2        # Delete ZFS dataset zroot/home/safreya/dataset_2
```

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:

```sh
% zfs rollback zroot/home/safreya@snap1
cannot rollback 'zroot/home/safreya': permission denied
```

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

```sh
% su -m root -c 'zfs allow safreya rollback zroot/home/safreya'
Password:
% zfs rollback zroot/home/safreya@snap1
```

## 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:

```sh
% su -m root -c 'zfs allow safreya change-key,load-key,keyformat,keylocation,encryption zroot/home/safreya'
Password: # Enter the root account password here and press Enter
```

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

```sh
% zfs allow zroot/home/safreya
---- Permissions on zroot/home/safreya -------------------------------
Local+Descendent permissions:
        user safreya change-key,create,destroy,encryption,keyformat,keylocation,load-key,mount,snapshot
```

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:

```sh
% zfs create -o encryption=on -o keyformat=passphrase zroot/home/safreya/secret
Enter new passphrase:     # Enter the passphrase here; it will not be echoed
Re-enter new passphrase:  # Re-enter the passphrase here; it will not be echoed
```

Check the encryption status:

```sh
% zfs get mounted zroot/home/safreya/secret        # Query whether the zroot/home/safreya/secret dataset is mounted
NAME                       PROPERTY  VALUE    SOURCE
zroot/home/safreya/secret  mounted   yes      -
```

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

```sh
% cd secret                                      # Enter the secret dataset directory
% echo "a secret makes a man mad" > abc.txt     # Create file abc.txt in the secret dataset and write content
% cd ..                                          # Return to the parent directory
% zfs unmount zroot/home/safreya/secret         # Unmount the secret dataset
% zfs unload-key zroot/home/safreya/secret      # Unload the encryption key of the secret dataset
% zfs get mounted zroot/home/safreya/secret     # Query whether the secret dataset is mounted
NAME                       PROPERTY  VALUE    SOURCE
zroot/home/safreya/secret  mounted   no       -
% ls secret # No output

```

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

```sh
% zfs load-key zroot/home/safreya/secret   # Load the encryption key of the secret dataset
Enter passphrase for 'zroot/home/safreya/secret':  # Prompt to enter the key passphrase
% zfs mount zroot/home/safreya/secret      # Mount the secret dataset
% ls secret                                 # List files in the secret dataset
Permissions Size User    Date Modified Name
.rw-r--r--    25 safreya 19 Sep 20:26  abc.txt
```

> **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:

```sh
% su -m root -c 'zfs unallow safreya destroy zroot/home/safreya'
Password:        # Enter the root account password here and press Enter
```

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

```sh
% zfs allow zroot/home/safreya
---- Permissions on zroot/home/safreya -------------------------------
Local+Descendent permissions:
        user safreya change-key,create,encryption,keyformat,keylocation,load-key,mount,rollback,snapshot
```

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.

```sh
# adduser        # Add a new user to the system, entering the username, password, and other information as prompted
Username: test

……irrelevant content omitted……

Enable ZFS encryption? (yes/no) [no]: yes #This is a new feature

……irrelevant content omitted……
ZFS dataset : zroot/home/test

Enter encryption keyphrase for ZFS dataset (zroot/home/test):
Enter new passphrase:
Re-enter new passphrase:
adduser: INFO: Successfully created ZFS dataset (zroot/home/test).
adduser: INFO: Successfully added (test) to the user database.
```

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

```sh
# zfs allow zroot/home/test
---- Permissions on zroot/home/test ----------------------------------
Local+Descendent permissions:
        user test create,destroy,mount,snapshot
```

Unmount the dataset and key:

```sh
# zfs unmount zroot/home/test        # Unmount the zroot/home/test dataset
# zfs unload-key zroot/home/test     # Unload the encryption key of the zroot/home/test dataset
```

Switch to the regular user `test` and try to mount:

```sh
# su test        # Switch to regular user test
$ zfs load-key zroot/home/test        # Load the encryption key of the zroot/home/test dataset
Enter passphrase for 'zroot/home/test':
Key load error: Permission denied.
```

`Permission denied` indicates insufficient permissions; access is denied.

## References

* OpenZFS Project. man zfs-allow\[EB/OL]. \[2026-04-02]. <https://openzfs.github.io/openzfs-docs/man/master/8/zfs-allow.8.html>. Official OpenZFS zfs-allow command manual.
* FreeBSD Project. zfs-allow -- delegate ZFS administration permissions to unprivileged users\[EB/OL]. \[2026-04-02]. <https://man.freebsd.org/cgi/man.cgi?query=zfs-allow&sektion=8>. Official FreeBSD zfs-allow command manual.
* FreeBSD Project. zfs-create -- create ZFS dataset\[EB/OL]. \[2026-04-02]. <https://man.freebsd.org/cgi/man.cgi?query=zfs-create&sektion=8>. Official FreeBSD zfs-create command manual.
* FreeBSD Project. FreeBSD Handbook, Chapter 22 The Z File System (ZFS)\[EB/OL]. \[2026-04-24]. <https://docs.freebsd.org/en/books/handbook/zfs/>. Chapter on ZFS in the FreeBSD Handbook.
* FreeBSD Foundation. OpenZFS Encryption Arrives on FreeBSD\[EB/OL]. (2020-07)\[2026-04-02]. <https://freebsdfoundation.org/wp-content/uploads/2020/07/OpenZFS-Encryption-Arrives-on-FreeBSD.pdf>. Explains the similarities and differences between GELI encryption and ZFS encryption.
* FreeBSD Project. Merge OpenZFS support in to HEAD\[EB/OL]. \[2026-04-02]. <https://cgit.freebsd.org/src/commit/?id=9e5787d2284e>. Commit record of FreeBSD 13.0 transitioning to OpenZFS.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-28-the-zfs-file-system/di-28.7-jie-zfs-wei-tuo-guan-li.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
