#!/usr/bin/env bash
# backup/restore/restore-from-b2.sh
# Fetch a backup date from B2 into /srv/homelab/restore/<date>/ and
# decompress the pieces into something we can actually inspect before
# clobbering the live data. This script never overwrites live state.
#
# Usage: restore-from-b2.sh YYYYMMDD [pg|sqlite|vols|all]
#
# Docs: mercemay.top/src/homelab-compose/
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
. "${HERE}/../../scripts/lib/log.sh"
DATE="${1:-}"
KIND="${2:-all}"
RCLONE_CONF="${RCLONE_CONF:-/srv/homelab/secrets/rclone.conf}"
REMOTE="${REMOTE:-b2-homelab:homelab-backups}"
DEST_ROOT="${DEST_ROOT:-/srv/homelab/restore}"
if [[ -z "${DATE}" ]]; then
echo "usage: $0 YYYYMMDD [pg|sqlite|vols|all]" >&2
exit 2
fi
if [[ ! "${DATE}" =~ ^[0-9]{8}$ ]]; then
echo "bad date: ${DATE}" >&2
exit 2
fi
DEST="${DEST_ROOT}/${DATE}"
install -d "${DEST}"
fetch() {
local sub="$1"
log_info "fetch ${sub}"
rclone --config "${RCLONE_CONF}" copy --fast-list \
"${REMOTE}/${DATE}/${sub}" "${DEST}/${sub}"
}
expand_pg() {
log_info "expand pg dumps"
find "${DEST}/pg" -type f -name '*.sql.zst' -print0 \
| while IFS= read -r -d '' f; do
local out="${f%.zst}"
zstd -q -d -f "${f}" -o "${out}"
done
}
expand_vols() {
log_info "expand volume archives"
local work="${DEST}/vols-extracted"
install -d "${work}"
find "${DEST}/vols" -type f -name '*.tar.zst' -print0 \
| while IFS= read -r -d '' f; do
local name
name=$(basename "${f}" .tar.zst)
install -d "${work}/${name}"
zstd -q -d -c "${f}" | tar -xf - -C "${work}/${name}"
done
}
case "${KIND}" in
pg)
fetch pg; expand_pg
;;
sqlite)
fetch sqlite
find "${DEST}/sqlite" -name '*.zst' -exec zstd -q -d -f {} \;
;;
vols)
fetch vols; expand_vols
;;
all)
fetch pg; expand_pg
fetch sqlite
find "${DEST}/sqlite" -name '*.zst' -exec zstd -q -d -f {} \;
fetch vols; expand_vols
;;
*)
echo "unknown kind: ${KIND}" >&2
exit 2
;;
esac
log_info "restored artifacts under ${DEST}"
log_info "nothing has been applied to live containers yet"