ZFS Move Over SSH
zfs-move-over-ssh.sh snapshots every ZFS filesystem at and beneath a source
dataset, then sends each snapshot to a remote ZFS server over SSH.
For a source tree such as:
tank/data
tank/data/documents
tank/data/media
and destination root backup/data, the script sends the filesystems to:
backup/data
backup/data/documents
backup/data/media
Each local snapshot is named move-YYYYMMDD-HHMMSS.
Requirements
- Run the script as an account that can use
zfson the source server. - The source host needs Bash, ZFS utilities, and SSH.
- The destination host needs ZFS utilities and the destination pool must exist.
- The SSH account on the destination must be able to execute
sudo -n zfswithout a password prompt. - SSH connectivity and host-key verification must already work.
The script is intended for one-shot full snapshot transfers. It does not use incremental sends or resume tokens.
Usage
bash zfs-move-over-ssh.sh [options] SOURCE_ROOT REMOTE_HOST DESTINATION_ROOT
Example:
bash zfs-move-over-ssh.sh tank/data root@new-server backup/data
Use a non-standard SSH key or port when needed:
bash zfs-move-over-ssh.sh \
--identity-file ~/.ssh/zfs-migration \
--ssh-port 2222 \
tank/data admin@new-server backup/data
Options:
| Option | Description |
|---|---|
-n, --dry-run |
Print planned snapshot, send, and receive commands without running them. |
-i, --identity-file FILE |
Use the specified SSH private key. |
-p, --ssh-port PORT |
Connect to the specified SSH port. |
--destroy-source-snapshots |
Remove each local migration snapshot only after its receive succeeds. |
-h, --help |
Show command help. |
Recommended Procedure
-
Confirm the source datasets:
zfs list -r tank/data -
Confirm remote privileged ZFS access:
ssh admin@new-server 'sudo -n zfs list' -
Preview the operation. Review every destination name in the output:
bash zfs-move-over-ssh.sh --dry-run tank/data admin@new-server backup/data -
Run the migration:
bash zfs-move-over-ssh.sh tank/data admin@new-server backup/data -
Verify the received datasets and data before retiring the source:
ssh admin@new-server 'sudo zfs list -r backup/data'
Safety and Recovery
- The script does not destroy source filesystems or source data.
- By default, the generated local snapshots remain on the source. This allows a
failed run to be inspected or sent again. Remove them manually only after
verification, or use
--destroy-source-snapshotsonce the workflow is trusted. - The remote command is
zfs receive -uF.-uleaves received filesystems unmounted.-Fcan roll back the destination filesystem and destroy newer snapshots or changes that conflict with the incoming snapshot. Do not point the script at a destination containing data you need unless you have reviewed the dry-run output and have a current backup. - The script processes one filesystem at a time. If it stops partway through, completed destination filesystems remain received. Re-running with the same source can create another timestamped snapshot; inspect both source and destination state before retrying.
- A successful transfer is not a destructive move. Verify applications and data on the destination, then perform any source cleanup separately.
Notes
The destination root itself does not have to exist before the transfer, but
its parent pool or filesystem must exist and the remote account must have ZFS
permission to create the target datasets. Dataset properties are included in
the stream through zfs send -p.