24.7 ZFS 委托管理
ZFS 提供全面的权限委托系统,允许非特权用户执行 ZFS 管理操作。
例如,如果每个用户的主目录是一个数据集,用户需要获得创建和销毁其主目录快照的权限。执行备份的用户可以获得使用复制功能的权限。
ZFS 还允许使用统计脚本,仅访问所有用户的空间使用数据。权限的委托能力本身也可委托。权限委托适用于每个子命令和大多数属性。
用户级 ZFS 管理
ZFS 委托管理(ZFS delegation)提供细粒度的权限控制,让系统管理员将特定的 ZFS 管理权限授予非特权用户。自 FreeBSD 14.1 起,adduser 会自动为非特权用户的 ZFS 主目录创建独立数据集并支持加密。
该变更(commit 516009ce8d38)使 adduser(8) 在用户主目录的父目录为 ZFS 数据集时,自动为用户创建独立 ZFS 数据集,例如 /home/xxx 继承自 /home。adduser 的 -Z 参数可禁用此行为,同时支持为非特权用户的 ZFS 主目录启用加密。
基础用户级 ZFS 管理
以非特权用户的 ZFS 数据集为例。安装系统时手动创建了两个普通用户 aria2 和 safreya。
列出系统中所有 ZFS 文件系统及其属性:
% 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 # 请注意此行
zroot/home/safreya 7.74G 396G 7.70G /home/safreya # 请注意此行
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其中:
即在创建用户时,系统已默认为用户 aria2 和 safreya 分别创建了各自独立的数据集 zroot/home/aria2 和 zroot/home/safreya。
接下来,分别查看两个数据集上的用户权限。
由输出可知,系统在创建用户时,会默认为其数据集授予 create、destroy、mount 和 snapshot 四项权限。
ZFS 委托权限存储在数据集的元数据中。Local+Descendent permissions 表示该权限设置既适用于当前数据集,其作用范围也覆盖其子数据集。
zfs allow <用户> allow <数据集> 赋予指定用户在目标数据集或其子数据集上将他们所拥有的任何权限委派给其他用户的能力。如果某用户拥有 snapshot 权限与 allow 权限,该用户可以将 snapshot 权限授予其他用户。
因此,对于这两个数据集,普通用户也可使用快照功能:
再来看 create、destroy 和 mount 权限:
创建新数据集涉及挂载,这要求将 FreeBSD 的 sysctl vfs.usermount 设置为 1,以允许非 root 用户挂载文件系统。
由输出可知,创建和销毁权限可正常运行。为了防止滥用,还有另一个限制:非 root 用户必须拥有挂载点的所有权,才能挂载文件系统。
至此,用户级 ZFS 管理的基本功能已就绪。但 rollback 权限默认不可用,需由 root 用户为普通用户单独授予。
将 zroot/home/safreya 文件系统回滚到 snap1 快照状态:
以 root 用户授予 safreya 用户对 zroot/home/safreya 文件系统执行回滚操作的权限:
用户级 ZFS 加密功能
在 FreeBSD 14.1 中,如果要在用户级使用 ZFS 加密功能,必须为用户授予特定权限。
授权用户 safreya 对 zroot/home/safreya 文件系统执行密钥管理和加密操作:
显示 zroot/home/safreya 文件系统的当前权限授权设置:
change-key、load-key、keyformat、keylocation 和 encryption 这五项权限属性用于 ZFS 的加密功能。
创建启用加密的 ZFS 数据集 zroot/home/safreya/secret,并将密码用作密钥格式:
查看加密情况:
查看 mounted 属性,加密数据集创建即挂载,现在创建一份文件,随后卸载加密数据集:
卸载加密数据集时必须同时卸载其密钥,挂载数据集时也必须先加载密钥:
警告
因为
destroy权限默认已授予用户,所以无论数据集是否挂载,destroy子命令都可以成功销毁数据集。因此如果操作者不是该用户本人,仍可能删除数据集。授权即授予普通用户代理权限,使其在操作授权的数据集时拥有类似 root 的权限,无需输入密码。因此,在授予权限时应合理限制授权范围和权限属性,例如禁用
destroy权限属性等。
撤销用户 safreya 对 zroot/home/safreya 文件系统的销毁权限:
显示 zroot/home/safreya 文件系统的当前权限授权设置:
此处,zroot/home/safreya/secret 受 zroot/home/safreya 上 Local+Descendent 权限的作用范围覆盖。ZFS 委托权限不存在继承机制,权限存储在授予它的数据集上,Local+Descendent 表示该权限的作用范围同时覆盖本数据集及其子孙数据集。在父数据集上撤销权限时,其 Descendent 范围也会移除,子孙数据集上的用户将失去相应权限。如果需要对子孙数据集单独控制权限,需要显式地在子孙数据集上授权或撤销。
adduser 与用户主目录加密
adduser 命令可直接使用加密的用户主目录数据集,但默认授予的权限不足,卸载后普通用户无法直接挂载。
查看 zroot/home/test 文件系统的当前权限授权设置:
卸载数据集和密钥:
切换到普通用户 test 尝试挂载:
Permission denied 表示权限不足,访问被拒绝。
参考文献
OpenZFS Project. man zfs-allow[EB/OL]. [2026-04-02]. https://openzfs.github.io/openzfs-docs/man/master/8/zfs-allow.8.html. OpenZFS 官方 zfs-allow 命令手册。
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. FreeBSD 官方 zfs-allow 命令手册。
FreeBSD Project. zfs-create -- create ZFS dataset[EB/OL]. [2026-04-02]. https://man.freebsd.org/cgi/man.cgi?query=zfs-create&sektion=8. FreeBSD 官方 zfs-create 命令手册。
FreeBSD Project. FreeBSD Handbook, Chapter 22 The Z File System (ZFS)[EB/OL]. [2026-04-24]. https://docs.freebsd.org/en/books/handbook/zfs/. FreeBSD 手册中关于 ZFS 的章节。
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. 说明 GELI 加密与 ZFS 加密的异同点。
FreeBSD Project. Merge OpenZFS support in to HEAD[EB/OL]. [2026-04-02]. https://cgit.freebsd.org/src/commit/?id=9e5787d2284e. FreeBSD 13.0 转向 OpenZFS 的提交记录。
最后更新于