One of Zelta's core design principles is operating safely with minimal privileges. Using ZFS delegation (zfs allow), you can grant non-root users exactly the permissions they need for replication—and nothing more.
This document covers ZFS permission delegation for Zelta operations, from basic replication to advanced features like rotation and encrypted dataset handling.
Running replication as root is convenient but unnecessary. With proper delegation:
Modern OpenZFS includes groundbreaking security features that make delegation even more powerful:
receive:append prevents destructive receives (zfs recv -F), eliminating a major class of data loss scenariossend:raw prevents senders from transmitting unencrypted data from encrypted datasets—even if the dataset is mounted and accessibleThese features enable security architectures that were previously impossible.
For OpenZFS 2.2+ (FreeBSD 14+, latest Illumos, cutting-edge Linux):
Sender (source system):
zfs allow -u backupuser hold,send,bookmark,snapshot sink
Receiver (target system):
zfs allow -u backupuser receive:append,create,mount,readonly,clone,rename,volmode,compression,recordsize tank/Backups
For older OpenZFS versions (most Linux distributions as of 2025, FreeBSD 13):
Sender:
zfs allow -u backupuser hold,send,snapshot sink
Receiver:
zfs allow -u backupuser receive,create,mount,readonly,clone,rename,compression,recordsize tank/Backups
Note: Legacy versions lack receive:append, send:raw, and volmode delegation. Without receive:append, users can perform destructive receives. Without volmode, you may encounter errors when replicating volumes (zvols).
Minimum for basic replication:
zfs allow -u backupuser send,snapshot sink
send: Required to transmit dataset snapshotssnapshot: Allows Zelta to create snapshots before replication (recommended for consistency)Recommended additions:
zfs allow -u backupuser hold,send,bookmark,snapshot sink
hold: Prevents snapshots from being destroyed during replication (safety feature)bookmark: Enables bookmark creation for more flexible incremental replicationFor encrypted datasets (OpenZFS 2.2+):
zfs allow -u backupuser hold,send:raw,bookmark,snapshot sink
send:raw: This is a game-changing security feature. It allows sending encrypted datasets in their encrypted form, but prevents the sender from transmitting unencrypted data. Even if an encrypted dataset is mounted and the sender has read access to the plaintext files, send:raw blocks them from sending an unencrypted stream. This provides unprecedented protection for encrypted datasets in multi-tenant or untrusted environments.Important: send without :raw allows users to send decrypted data if the encrypted dataset is mounted. For encrypted datasets, always use send:raw instead of send.
Minimum for basic replication (modern):
zfs allow -u backupuser receive:append,create,mount,readonly tank/Backups
receive:append: Allows receiving new snapshots but prevents destructive receives (zfs recv -F). This is a critical safety feature—one of Zelta's core design goals is never requiring destructive operationscreate: Required to create new datasets during recursive replicationmount: Allows setting the mountpoint property (even though backups shouldn't be mounted)readonly: Allows setting replicas to read-only (strongly recommended)Recommended for production:
zfs allow -u backupuser receive:append,create,mount,readonly,clone,rename,volmode,compression,recordsize tank/Backups
clone: Required for zelta clone, zelta revert, and zelta rotaterename: Required for zelta revert and zelta rotate (these operations rename datasets as part of their workflow)volmode: Required for replicating volumes (zvols). On legacy systems without this delegation, you may see the error: operation not applicable to datasets of this typecompression: Allows preserving compression settings from source. Without this, receivers cannot set compression properties, which can cause issues during failover or if you want to recompress backups with different settingsrecordsize: Allows preserving recordsize settings. Critical for maintaining performance characteristics during failoverLegacy systems (without receive:append):
zfs allow -u backupuser receive,create,mount,readonly,clone,rename,compression,recordsize tank/Backups
Note: Without receive:append, the user can perform destructive receives. This is less than ideal but may be necessary on older systems.
For environments where you want to grant broader permissions (testing, single-tenant systems, or when you trust the backup user completely):
Permissive sender:
zfs allow -u backupuser hold,send,send:raw,bookmark,snapshot,destroy sink
Permissive receiver:
zfs allow -u backupuser receive,receive:append,create,mount,mountpoint,canmount,readonly,clone,rename,volmode,compression,recordsize,setuid,exec,atime,destroy tank/Backups
These grant additional property permissions and destroy for snapshot management. Use with caution.
zelta backup, zelta sync)Sender: send,snapshot (minimum) or hold,send,bookmark,snapshot (recommended)
Receiver: receive:append,create,mount,readonly (minimum) or add compression,recordsize (recommended)
zelta clone)On the pool containing the dataset to clone:
zfs allow -u backupuser clone tank/Backups
Creates a writable clone for recovery or testing without modifying the original backup.
zelta revert)On the dataset being reverted:
zfs allow -u backupuser clone,rename sink/dataset
Rewinds a dataset to a previous snapshot by renaming and cloning in place.
zelta rotate)On both source and target:
zfs allow -u backupuser clone,rename sink/dataset
zfs allow -u backupuser clone,rename,receive:append tank/Backups/dataset
Performs multi-way rename and clone operations to preserve divergent histories. This is Zelta's most sophisticated operation and requires both clone and rename permissions.
From the zfs-allow man page:
Delegations are supported under Linux with the exception of mount, unmount, mountpoint, canmount, rename, and share. These permissions cannot be delegated because the Linux mount(8) command restricts modifications of the global namespace to the root user.
However, in practice, Zelta works correctly on Linux despite this limitation. The behavior of these operations may not be delegated, but the properties are still set correctly. Zelta's testing confirms:
mountpoint is reset to inheritcanmount is set to noautoreadonly is set correctlySo while Linux won't allow the backup user to actually mount/unmount datasets, the properties are delegated and Zelta operates safely.
FreeBSD 14+ includes OpenZFS 2.3.4 with full support for modern delegation features including receive:append, send:raw, and volmode.
FreeBSD 13 uses an older OpenZFS version and requires legacy permission syntax.
Modern Illumos distributions include current OpenZFS with full delegation support.
The receiver lacks necessary permissions. Common causes:
receive or receive:append permissioncreate permission for recursive replicationcompression, recordsize)Check current delegations:
zfs allow tank/Backups
You're likely replicating a volume (zvol) and the receiver lacks volmode permission. This delegation is only available on OpenZFS 2.2+.
Workaround for legacy systems: Grant broader receive permissions or use root for volume replication.
The sender lacks necessary permissions. Common causes:
send permissionsnapshot permission (if Zelta needs to create a snapshot)send:raw permissionIf properties like compression or recordsize aren't being preserved on the target:
zfs allow -u backupuser compression,recordsize tank/Backups
Zelta will warn you if the receiver lacks permissions for properties it's trying to set.
Grant only the permissions required for your use case. Start with minimum permissions and add more as needed.
For encrypted datasets, always use send:raw instead of send. This prevents the sender from transmitting unencrypted data, even if they have filesystem-level access to the mounted dataset.
Modern OpenZFS's receive:append prevents destructive receives, eliminating an entire class of data loss scenarios. If you're on a legacy system without this feature, consider:
While delegation is preferred, there are scenarios where root access is reasonable:
Root access for replication is not inherently dangerous—Zelta's safe defaults prevent data destruction regardless of privilege level. The risk is operational: root can accidentally destroy data through other means.
After setting up delegations, test with zelta match:
zelta match backupuser@source:sink/dataset backupuser@target:tank/Backups/dataset
If this succeeds, your permissions are correctly configured for replication.
Test a full replication:
zelta backup backupuser@source:sink/dataset backupuser@target:tank/Backups/dataset
Zelta will report any missing permissions it encounters.
If you encounter permission issues:
zfs allow <dataset>zfs version or zpool upgrade -vFor more assistance:
For ZFS-specific delegation questions:
man zfs-allow - ZFS delegation documentation