fleet-manager: add backup.sh for the durable-state volumes

Snapshot fleet-data (inventory + admins.json + enroll.key — the admin-lockout
risk) and influx-data to timestamped tarballs via a throwaway alpine container
(read-only, live-safe), with BACKUP_KEEP retention. Documented in DEPLOY.md
Backups with a restore pointer.
This commit is contained in:
Audiobuzz
2026-07-05 00:34:23 +00:00
parent 487c62c53f
commit f72cea6b17
2 changed files with 69 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# backup.sh — snapshot the fleet-manager durable state to timestamped tarballs.
#
# Two docker named volumes hold everything that isn't reproducible from the image:
# - fleet-data : inventory.json + admins.json + enroll.key (CRITICAL — losing
# admins.json/enroll.key locks every admin out of the UI)
# - influx-data : the metrics time-series (history; regenerates going forward)
#
# Runs a throwaway alpine container to tar each volume read-only into $DEST. Safe
# to run live. Schedule it (systemd timer / cron); copy $DEST offsite.
#
# Usage:
# ./backup.sh [dest-dir] # default dest: ./backups
# COMPOSE_PROJECT_NAME=foo ./backup.sh # if you run compose under another project
#
# Restore (manager stopped):
# docker run --rm -v <project>_fleet-data:/dest -v "$PWD/backups":/src alpine \
# sh -c 'rm -rf /dest/* && tar xzf /src/fleet-data-YYYYmmdd-HHMMSS.tar.gz -C /dest'
set -euo pipefail
DEST=${1:-./backups}
PROJECT=${COMPOSE_PROJECT_NAME:-fleet-manager} # compose derives volume names as <project>_<key>
STAMP=$(date -u +%Y%m%d-%H%M%S)
VOLUMES=${BACKUP_VOLUMES:-"fleet-data influx-data"}
mkdir -p "$DEST"
DEST_ABS=$(cd "$DEST" && pwd)
for key in $VOLUMES; do
vol="${PROJECT}_${key}"
if ! docker volume inspect "$vol" >/dev/null 2>&1; then
echo "backup: SKIP $vol (no such volume — wrong COMPOSE_PROJECT_NAME?)"
continue
fi
out="${key}-${STAMP}.tar.gz"
echo "backup: $vol -> $DEST_ABS/$out"
docker run --rm \
-v "${vol}:/src:ro" \
-v "${DEST_ABS}:/backup" \
alpine tar czf "/backup/${out}" -C /src .
done
# Retention: keep the newest $KEEP of each volume's tarballs (0 = keep all).
KEEP=${BACKUP_KEEP:-14}
if [ "$KEEP" -gt 0 ]; then
for key in $VOLUMES; do
# ls -t for mtime order; our filenames are safe (key + UTC timestamp).
# shellcheck disable=SC2012
ls -1t "$DEST_ABS/${key}-"*.tar.gz 2>/dev/null | tail -n +"$((KEEP + 1))" | while read -r old; do
echo "backup: prune $old"
rm -f "$old"
done
done
fi
echo "backup: done ($STAMP) — copy $DEST_ABS offsite."