Skip to content

Instantly share code, notes, and snippets.

@harmoniqpunk
Last active March 11, 2024 21:33
Show Gist options
  • Save harmoniqpunk/59e42d9c5e777e70ab0f5faf3a6517c1 to your computer and use it in GitHub Desktop.
Save harmoniqpunk/59e42d9c5e777e70ab0f5faf3a6517c1 to your computer and use it in GitHub Desktop.
FreeBSD ZFS incremental backup in OVH Cold Archive. zroot snapshots are stored in an encrypted dataset inside the main pool
#!/bin/sh
set -e
# Configuration
zpool="bbox"
snapshot_prefix="${zpool}-" # Identify your ZPOOL daily snapshots
retention_count=36 # Number of snapshots per container
# Generate snapshot name with date
snapshot_name="${snapshot_prefix}"`date +%Y-%m-%d-%H-%M-%S`
zroot_snapshot_name="zroot-"`date +%Y-%m-%d-%H-%M-%S`
echo "Create zroot@${zroot_snapshot_name}"
zfs snapshot -r zroot@${zroot_snapshot_name}
echo "Start zroot@${zroot_snapshot_name} transfer"
# ZROOT Find the oldest incremental snapshot to base the transfer on
oldest=$(zfs list -t snapshot -o name -r zroot | grep zroot@ | tail -n 2 | head -n 1)
count=$(zfs list -t snapshot -o name -r zroot | grep zroot@ | wc -l)
echo "Oldest snapshot is: ${oldest}"
# Check the existance of a previous older ZROOT snapshot
if [ -n "$oldest" ] && [ "$count" -ge 2 ]; then
# Do an incremental send
echo "Start incremental send of zroot@${zroot_snapshot_name} (based on ${oldest})"
zfs send -Ri ${oldest} zroot@${zroot_snapshot_name} | gzip > /mnt/zroot/${zroot_snapshot_name}.data.gz
else
# No base snapshot found, do a full send
echo "Start full send of zroot@${zroot_snapshot_name}"
zfs send -R zroot@${zroot_snapshot_name} | gzip > /mnt/zroot/${zroot_snapshot_name}.data.gz
fi
echo "Create ${zpool}@${snapshot_name}"
zfs snapshot -r ${zpool}@${snapshot_name}
# ZPOOL Find the oldest incremental snapshot to base the transfer on
oldest=$(zfs list -t snapshot -o name -r ${zpool} | grep ${zpool}@ | tail -n 2 | head -n 1)
count=$(zfs list -t snapshot -o name -r ${zpool} | grep ${zpool}@ | wc -l)
# Check the existance of a previous older ZPOOL snapshot
if [ -n "$oldest" ] && [ "$count" -ge 2 ]; then
# Do an incremental send
echo "Start incremental send of ${zpool}@${snapshot_name} (based on ${oldest})"
zfs send -Rwi ${oldest} ${zpool}@${snapshot_name} | gzip > /tmp/${snapshot_name}.data.gz
else
# No base snapshot found, do a full send
echo "Start full send of ${zpool}@${snapshot_name}"
zfs send -Rw ${zpool}@${snapshot_name} | gzip > /tmp/${snapshot_name}.data.gz
echo "Create new OVH Cold Archive Container (bucket: ${snapshot_name})"
aws --endpoint-url https://s3.rbx-archive.io.cloud.ovh.net --region rbx-archive s3 mb s3://${snapshot_name}
fi
# Upload to Cold Archive
bucket=$(zfs list -t snapshot -o name -r ${zpool} | grep ${zpool}@ | tail -n +1 | head -n 1 | awk -F '@' '{print $2}')
echo "Start copy /tmp/${snapshot_name}.data.gz to OVH Cold Archive ${bucket} container"
rclone copy /tmp/${snapshot_name}.data.gz ovh:${bucket}
# Check for successful upload
if [ $? -eq 0 ]; then
# Clean up if upload succeeded
echo "Clean up tmp folder"
rm /tmp/${snapshot_name}.data.gz
else
# Exit with a failure status if upload failed
echo "Upload failed. Exiting script."
exit 1
fi
# Delete old ZROOT snapshots (beyond the retention count)
old_snapshots=$(zfs list -t snapshot -o name -r zroot | grep zroot@ | tail -n +${retention_count})
if [ -n "$old_snapshots" ]; then
echo "Deleting old zroot snapshots:"
echo "$old_snapshots"
zfs destroy -r $old_snapshots
fi
# Delete old ZPOOL snapshots (beyond the retention count)
old_snapshots=$(zfs list -t snapshot -o name -r ${zpool} | grep ${zpool}@ | tail -n +${retention_count})
if [ -n "$old_snapshots" ]; then
echo "Archive zfs bucket in OVH Cold Storage"
aws put-ovh-archive --bucket ${bucket}
trap 'echo "Cold Archive failed. Exiting..." | mail -s "Cold Archive Error" admin@harmoniis.com; exit 1' EXIT
echo "Deleting old ${zpool} snapshots:"
echo "$old_snapshots"
zfs destroy -r $old_snapshots
fi
echo "Completed"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment