add btrfs snapshot encrypted backup script
This commit is contained in:
parent
f6fe57aaf1
commit
22ae5b84e0
79
backup.sh
Executable file
79
backup.sh
Executable file
|
@ -0,0 +1,79 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e -o pipefail
|
||||||
|
mkdir -p /backups
|
||||||
|
chmod 750 /backups
|
||||||
|
chown root:sudo /backups
|
||||||
|
mkdir -p /snapshots
|
||||||
|
chmod 700 /snapshots
|
||||||
|
chown root:root /snapshots
|
||||||
|
name=""
|
||||||
|
clone_sources=()
|
||||||
|
while (( $# > 0 )); do
|
||||||
|
case "$1" in
|
||||||
|
-n)
|
||||||
|
name="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-c)
|
||||||
|
clone_sources+=(-c "$2")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cat <<EOF >&2
|
||||||
|
usage: sudo $0 [-n <name-suffix>] [-c <clone-source-snapshot-name>]
|
||||||
|
creates a encrypted backup of the btrfs subvolume mounted at '/' and uses all
|
||||||
|
the '-c' options as clone source snapshots to reduce the size of the
|
||||||
|
final file. see 'man btrfs-send' for details of how '-c' works.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if [[ -n "$name" ]]; then
|
||||||
|
name="-$name"
|
||||||
|
fi
|
||||||
|
name="snap-$(date --iso-8601=date -u)$name"
|
||||||
|
echo "final base name: '$name'"
|
||||||
|
if [[ "$1" =~ ^'-' ]]; then
|
||||||
|
cat <<'EOF' >&2
|
||||||
|
usage: sudo ./backup.sh [<name>]
|
||||||
|
creates a encrypted backup of the btrfs subvolume mounted at `/`
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "creating btrfs snapshot with name: '$name'"
|
||||||
|
zst_name="$name.btrfs.zst"
|
||||||
|
out_name="/backups/$zst_name.gpg"
|
||||||
|
prompt=0
|
||||||
|
if [[ -d /snapshots/"$name" ]]; then
|
||||||
|
prompt=1
|
||||||
|
echo "snapshot already exists: /snapshots/$name" >&2
|
||||||
|
fi
|
||||||
|
if [[ -f "$out_name" ]]; then
|
||||||
|
prompt=1
|
||||||
|
echo "output file already exists: $out_name" >&2
|
||||||
|
fi
|
||||||
|
mapfile -t existing_backups < <(find /backups/ -maxdepth 1 -name 'snap-*.btrfs.zst.gpg' -print)
|
||||||
|
for existing_backup in "${existing_backups[@]}"; do
|
||||||
|
if [[ "$existing_backup" != "$out_name" ]]; then
|
||||||
|
echo "other backup files exist, you should copy them to a remote system and then delete them." >&2
|
||||||
|
echo "If you don't delete them, they will be included in this backup, using waay more space than necessary." >&2
|
||||||
|
printf "e.g., run: sudo rm %q\n" "$existing_backup" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if ((prompt)); then
|
||||||
|
if read -r -p "snapshot and/or output file already exists, do you want to overwrite them? [y/n]: " -t 300 REPLY && [[ "$REPLY" =~ ^[yY]$ ]]; then
|
||||||
|
btrfs subvolume delete /snapshots/"$name"
|
||||||
|
rm -f "$out_name"
|
||||||
|
else
|
||||||
|
echo "exiting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
btrfs subvolume snapshot -r / /snapshots/"$name"
|
||||||
|
echo "encrypting and writing to: $out_name"
|
||||||
|
exec 3<&0
|
||||||
|
btrfs send "${clone_sources[@]}" /snapshots/"$name" | zstd --fast -T0 | gpg --symmetric --compress-algo none --set-filename "$zst_name" -o- /dev/fd/4 4<&0- <&3 > "$out_name"
|
||||||
|
echo "written to: $out_name"
|
Loading…
Reference in a new issue