Overview
ZFS send/receive allows you to:
- Create full or incremental backups
- Replicate datasets between systems
- Migrate data between pools
- Clone environments efficiently
Basic Send/Receive
Full Send
# Send to file
zfs send tank/data@snap1 > /backup/data-snap1.zfs
# Send to another pool (same system)
zfs send tank/data@snap1 | zfs receive backup/data
# Compressed send (saves bandwidth)
zfs send tank/data@snap1 | gzip > /backup/data-snap1.zfs.gzReceive Options
# Basic receive
zfs receive backup/data < /backup/data-snap1.zfs
# Force receive (destroys existing)
zfs receive -F backup/data
# Don't mount after receive
zfs receive -u backup/data
# Verbose output
zfs receive -v backup/dataIncremental Backups
# First: full backup
zfs snapshot tank/data@monday
zfs send tank/data@monday | zfs receive backup/data
# Later: incremental (only changes)
zfs snapshot tank/data@tuesday
zfs send -i tank/data@monday tank/data@tuesday | zfs receive backup/data
# Incremental from most recent snapshot
zfs send -I tank/data@monday tank/data@friday | zfs receive backup/data
# This sends monday->tuesday->wednesday->thursday->fridayRemote Replication
Via SSH
# Send to remote system
zfs send tank/data@snap1 | ssh backup-server zfs receive backup/data
# Compressed transfer
zfs send tank/data@snap1 | gzip | ssh backup-server "gunzip | zfs receive backup/data"
# Incremental to remote
zfs send -i tank/data@snap1 tank/data@snap2 | ssh backup-server zfs receive backup/data
# Resume interrupted transfer (ZFS 0.7+)
zfs send -t <token> | ssh backup-server zfs receive -s backup/dataWith mbuffer (Faster)
# Install mbuffer
pkg install mbuffer
# Use with send/receive
zfs send tank/data@snap1 | mbuffer -s 128k -m 1G | ssh backup-server "mbuffer -s 128k -m 1G | zfs receive backup/data"Raw Send (Encrypted)
# Send encrypted dataset (keeps encryption)
zfs send -w tank/encrypted@snap1 | zfs receive backup/encrypted
# Raw send preserves:
# - Encryption
# - Compression (already compressed blocks)
# - Dedup referencesReplication Properties
# Send with properties
zfs send -p tank/data@snap1 | zfs receive backup/data
# Send recursively (all children)
zfs send -R tank/data@snap1 | zfs receive backup/data
# Exclude properties on receive
zfs receive -x mountpoint -x quota backup/dataAutomated Replication Script
#!/bin/sh
# /usr/local/bin/zfs-replicate.sh
SRC_DATASET="tank/data"
DST_HOST="backup-server"
DST_DATASET="backup/data"
SNAP_PREFIX="auto"
# Get latest snapshots
LAST_SRC=$(zfs list -H -o name -t snapshot -S creation "${SRC_DATASET}" | grep "@${SNAP_PREFIX}" | head -1)
LAST_DST=$(ssh ${DST_HOST} "zfs list -H -o name -t snapshot -S creation ${DST_DATASET} 2>/dev/null | grep @${SNAP_PREFIX} | head -1")
# Create new snapshot
NEW_SNAP="${SRC_DATASET}@${SNAP_PREFIX}-$(date +%Y%m%d-%H%M)"
zfs snapshot "${NEW_SNAP}"
if [ -z "${LAST_DST}" ]; then
# Full send
zfs send "${NEW_SNAP}" | ssh ${DST_HOST} "zfs receive -F ${DST_DATASET}"
else
# Incremental send
LAST_DST_NAME=$(echo ${LAST_DST} | cut -d@ -f2)
zfs send -i "@${LAST_DST_NAME}" "${NEW_SNAP}" | ssh ${DST_HOST} "zfs receive ${DST_DATASET}"
fi
echo "Replication complete: ${NEW_SNAP}"Troubleshooting
# Check receive token (for resume)
zfs get receive_resume_token backup/data
# Destroy partial receive
zfs receive -A backup/data
# View estimated send size
zfs send -nv tank/data@snap1
zfs send -nvi tank/data@snap1 tank/data@snap2 # IncrementalTools
- zrepl - ZFS replication daemon
- znapzend - ZFS backup with retention
- sanoid/syncoid - Policy-driven snapshots and replication
- zfs
- backup
- replication
- send
- receive
- freebsd