This page is the short path from installation to a verified backup. For full setup details, see Installation & Configuration, SSH Configuration, and ZFS Allow Delegation.
# Latest (may include beta features)
curl -fsSL https://zelta.space/web-install.sh | sh
# Latest release branch
curl -fsSL https://zelta.space/web-install.sh | sh -s -- --branch=release/1.2
Run as root for a system install or as a backup user for a user-local install. No git required.
git clone https://github.com/bell-tower/zelta.git
cd zelta
sudo ./install.sh
Zelta is available in FreeBSD ports. Ports may lag the GitHub release; use the installer for current 1.2 features.
pkg install zelta
For detailed installation instructions and configuration options, see Installation & Configuration.
Zelta uses an SCP-like syntax to specify datasets and snapshots:
Format: [username@][hostname:]pool[/dataset][@snapshot]
Examples:
tank/dataserver10.biz:tank/filesbackup@server11.biz:pool/stufftwin@server12.biz:sink/log@todayreadonly=onzfs allow for delegationZelta does not need to be installed on backup sources or targets—SSH keys and agent forwarding let you manage all replication from a single host. With ZFS delegation, there's no need to run Zelta as root either.
On source systems, delegate send permissions:
# As root, grant minimal permissions to backup user
zfs allow -u backupuser bookmark,hold,send:raw,snapshot sink/data
On target systems, delegate receive permissions:
# As root, grant receive permissions
zfs allow -u backupuser receive:append,create,mount,readonly,clone,rename,volmode,compression,recordsize tank/backups
The above uses modern OpenZFS delegation features. Use plain send or receive only when your platform lacks send:raw or receive:append, or when a separate high-trust role intentionally needs broader authority. See our detailed guides:
Before replicating, let's see what we're working with:
zelta match tank/data tank/backups/data
This shows the relationship between two dataset trees: matching snapshots, discrepancies, or whether one side is missing. It is the safest first command before backup or recovery work.
Replicate a dataset tree to a local backup:
zelta backup tank/data tank/backups/data
What just happened:
tank/data tree was replicated recursivelyreadonly=oninheritRun the same command again later to update incrementally. Zelta automatically detects the optimal zfs send method.
The syntax is identical for remote replication:
zelta backup tank/data backup@storage.example.com:pool/backups/data
Zelta uses SSH to stream the replication. Make sure you've set up SSH keys and zfs allow permissions on both systems.
Confirm everything matches:
zelta match tank/data backup@storage.example.com:pool/backups/data
You should see matching snapshots across the entire tree.
For multiple backup jobs, use zelta policy with a config file instead of scheduling individual commands.
A minimal zelta.conf:
SNAP_NAME: "$(date -u +auto-%Y-%m-%d_%H-%M)"
Production:
app-server-01:
- tank/www: tank/Backups/app-server-01/www
- tank/database: tank/Backups/app-server-01/database
Then run all jobs:
zelta policy
Or target a specific site or host:
zelta policy Production
zelta policy app-server-01
Schedule it with cron to keep backups current automatically. For composable policies with shared rules and multiple targets, see Policy Guide and the centralized policy example.
After the first backup, expand from direct commands into policies and recovery testing.
zelta revert: Roll back a dataset in place without losing current statezelta rotate: Handle divergent histories without destructive receiveszelta clone: Create temporary read-write copies for testingzelta prune and zprune: Plan and execute snapshot pruning as separate stepszelta snapshot: Create recursive snapshots on local or remote endpointszelta failover: Promote a backup target safelyzelta rebase: Move a production tree to an upgraded upstream while keeping backup continuityRun zelta usage for quick command reference, or zelta help for the full manual.