Configure destinations
Replication creates an independent copy only when the destination is on different storage. Boomerangz supports destinations on the same host, over SSH, and through a secured native listener.
Local destination
The recommended general-purpose layout uses discard=first: create a persistent destination container on different storage and delegate the receive permissions to the service account:
sudo zfs create backup/boomerangz
sudo zfs allow -u boomerangz \
canmount,create,destroy,mount,receive:append,userprop \
backup/boomerangzThe container may remain mounted. Boomerangz leaves its mount state and properties unchanged. Received filesystems and intermediate filesystems below it use canmount=noauto, preventing automatic mounting while allowing an administrator to mount a replica explicitly for recovery.
Select it on the source:
sudo zfs set \
org.boomerangz:discard=first \
org.boomerangz:local=backup/boomerangz \
tank/dataWith source tank/data, this creates backup/boomerangz/data. Use all to create only backup/boomerangz/data when the source is nested more deeply, but ensure leaf names cannot collide. Use off only when the configured path itself should be replica-owned: leave that path absent and delegate the same permissions on its existing parent. A reseed can destroy and recreate an off destination, including any local properties or delegation set directly on it. See Receive path mapping for the full layout and mounting implications.
SSH destination
SSH works without installing Boomerangz on the destination. When it is installed, the restricted ssh-shell endpoint provides a narrower command surface.
| Endpoint | Destination requirement | When to choose it |
|---|---|---|
direct | OpenSSH and OpenZFS tools | Boomerangz cannot be installed remotely. |
ssh-shell | Boomerangz installed remotely | Preferred when the packaged restricted account is available. |
auto | OpenSSH and OpenZFS tools | Try ssh-shell, then use direct if that endpoint is unavailable. |
Remote discovery happens when transfer work is due or explicitly retried, not on every ordinary local policy scan.
Prepare the ssh-shell account
When Boomerangz is installed from a package on the receiving host, use its existing boomerangz system account. The package sets /usr/lib/boomerangz/boomerangz-shell as this account's login shell and registers the wrapper in /etc/shells. The wrapper ignores SSH command arguments and starts only the restricted replication service; it does not provide an interactive shell.
Create the account's SSH directory:
sudo install -d -m 0700 -o boomerangz -g boomerangz /var/lib/boomerangz/.sshCreate the destination dataset and delegate its receive permissions:
sudo zfs create tank/backups
sudo zfs allow -u boomerangz \
canmount,create,destroy,mount,receive:append,userprop \
tank/backupsThis prepares tank/backups as a persistent first or all container. Select one of those strategies on each source that uses this remote. For off, leave the configured remote root absent and place the delegation on its existing parent instead.
Allow the restricted service to access this destination root in the receiving host's Boomerangz configuration:
[ssh_shell]
replication_roots = ["tank/backups"]Every request is checked against this server-side list. Restart the receiving host's daemon after changing shared configuration. Each new SSH session reads the current configuration itself.
Prepare a direct-SSH account
For a direct-SSH destination without Boomerangz, create a dedicated boomerangz-replication system user. This account is separate from the packaged daemon account and has a state-directory home rather than a regular user home:
sudo useradd --system --user-group --create-home \
--home-dir /var/lib/boomerangz-replication \
--shell /bin/sh boomerangz-replication
sudo install -d -m 0700 \
-o boomerangz-replication -g boomerangz-replication \
/var/lib/boomerangz-replication/.sshDelegate only the destination permissions to this account:
sudo zfs create tank/backups
sudo zfs allow -u boomerangz-replication \
canmount,create,destroy,mount,receive:append,userprop \
tank/backupsThis prepares tank/backups as a persistent first or all container. For off, leave the configured remote root absent and delegate on its existing parent instead.
Do not add boomerangz-replication to administrative groups, give it source dataset permissions, or grant it sudo access. Direct mode must execute a small set of zfs and zpool commands through its login shell, so the narrow account and ZFS delegation form its main authorization boundary.
Delegate every additional receive property selected through set_prop:<name> or ignore_prop:<name>.
Install a dedicated key
Generate a key dedicated to this destination. Do not reuse a personal key:
sudo ssh-keygen -t ed25519 \
-f /etc/boomerangz/credentials.d/home-backup-ed25519 \
-C boomerangz-home-backup
sudo chown root:boomerangz /etc/boomerangz/credentials.d/home-backup-ed25519
sudo chmod 0640 /etc/boomerangz/credentials.d/home-backup-ed25519Install only the public key for the receiving account. For ssh-shell, add it to /var/lib/boomerangz/.ssh/authorized_keys with OpenSSH's restrictions:
restrict ssh-ed25519 AAAA... boomerangz-home-backupThe account's packaged login shell is the command restriction. The client sends the requested destination root through the replication API, and ssh_shell.replication_roots determines whether the receiving host accepts it. Do not change this account back to a general-purpose shell.
For direct mode, add the key to /var/lib/boomerangz-replication/.ssh/authorized_keys and retain restrict:
restrict ssh-ed25519 AAAA... boomerangz-home-backupDirect mode can run the remote OpenZFS commands required for replication. Contain it with a dedicated account, filesystem permissions, and narrow ZFS delegation.
Verify the host-key fingerprint through a separate trusted channel and add it to the service account's known_hosts file. Strict host-key checking is always enabled.
Configure the sender
[remotes.home-backup]
transport = "ssh"
endpoint = "ssh-shell"
host = "backup.example.net"
port = 22
user = "boomerangz"
root = "tank/backups"
identity_file = "/etc/boomerangz/credentials.d/home-backup-ed25519"
ssh_shell_path = "/usr/lib/boomerangz/boomerangz-shell"
connect_timeout = "10s"For the direct fallback account, change the endpoint and user:
endpoint = "direct"
user = "boomerangz-replication"For a packaged ssh-shell destination, explicitly naming /usr/lib/boomerangz/boomerangz-shell documents and verifies the intended remote endpoint. The account's restricted login shell still ignores the SSH-supplied command and arguments. The application's current fallback when ssh_shell_path is omitted is to resolve boomerangz through the remote account's command path.
Use auto only when the same configured SSH account is deliberately able to support the fallback. The packaged boomerangz account is intentionally restricted to ssh-shell and cannot run direct commands.
Native secured destination
A native destination uses a configured TCP listener and an imported pairing.
Configure the receiving host
Create the destination dataset and delegate its receive permissions on the host that will store the replica:
sudo zfs create tank/backups
sudo zfs allow -u boomerangz \
canmount,create,destroy,mount,receive:append,userprop \
tank/backupsThis prepares tank/backups as a persistent first or all container. For off, leave the configured listener root absent and delegate on its existing parent instead.
Configure the listener on that receiving host:
[listeners.replication]
network = "tcp"
address = "0.0.0.0:7443"
advertised_address = "backup.example.net:7443"
auth_mode = "mtls+token"
replication_roots = ["tank/backups"]When tls_cert and tls_key are omitted, Boomerangz creates and renews a private server identity. advertised_address must contain the DNS name or IP address that clients use, followed by the port. A stable DNS name is generally preferable; wildcard listening addresses such as 0.0.0.0 and :: are not client identities.
Create a narrowly scoped pairing on the receiving host and transfer the output through a trusted channel:
umask 077
sudo boomerangz pairing create \
--listener replication \
--scope replicate >home-backup-pairing.jsonConfigure the source host
Transfer home-backup-pairing.json to the source host through a trusted channel, then import it there:
sudo boomerangz pairing import home-backup home-backup-pairing.jsonAdd the native destination to the source host's configuration:
[remotes.home-backup]
transport = "native"
credential = "home-backup"
root = "tank/backups"Treat pairing bundles as secrets. See Secure your deployment for authentication choices and certificate trust.