Add three-scenario disaster recovery
This commit is contained in:
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a browser-downloadable, encrypted archive of irreplaceable Athena data.
|
||||
set -Eeuo pipefail
|
||||
umask 077
|
||||
|
||||
OUTPUT_DIR=${ATHENA_EXPORT_DIR:-/data/emergency-backups}
|
||||
RECIPIENT_FILE=${ATHENA_AGE_RECIPIENT_FILE:-/etc/mike-ai/recovery.age-recipient}
|
||||
STATE=/var/lib/mike-ai-disaster-backup/latest
|
||||
KEEP=${ATHENA_EXPORT_KEEP:-5}
|
||||
|
||||
log() { printf '\n==> %s\n' "$*"; }
|
||||
die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[[ $EUID -eq 0 ]] || die "Bitte als root ausführen."
|
||||
[[ -s $RECIPIENT_FILE ]] || die "Age-Empfänger fehlt: $RECIPIENT_FILE"
|
||||
[[ $KEEP =~ ^[1-9][0-9]*$ ]] || die "ATHENA_EXPORT_KEEP muss positiv sein."
|
||||
for command in age zstd tar docker sha256sum flock; do
|
||||
command -v "$command" >/dev/null || die "$command fehlt."
|
||||
done
|
||||
exec 9>/run/lock/athena-export-backup.lock
|
||||
flock -n 9 || die "Ein exportierbares Backup läuft bereits."
|
||||
|
||||
install -d -m 0755 "$OUTPUT_DIR"
|
||||
install -d -m 0700 "$STATE"
|
||||
|
||||
log "Aktuellen Docker-Zustand sichern"
|
||||
docker exec mike-ai-backup backup
|
||||
latest=$(readlink -f /data/docker-backups/athena-latest.tar.gz)
|
||||
[[ -s $latest ]] || die "Docker-Zustandsbackup fehlt."
|
||||
gzip -t "$latest" || die "Docker-Zustandsbackup ist beschädigt."
|
||||
install -m 0600 "$latest" "$STATE/docker-state.tar.gz"
|
||||
|
||||
stamp=$(date -u +%Y-%m-%dT%H-%M-%SZ)
|
||||
name="athena-portable-$stamp.tar.zst.age"
|
||||
partial="$OUTPUT_DIR/.$name.partial"
|
||||
target="$OUTPUT_DIR/$name"
|
||||
list=$(mktemp /tmp/athena-export-list.XXXXXX)
|
||||
trap 'rm -f "$list" "$partial"' EXIT
|
||||
|
||||
add_path() {
|
||||
local path=${1#/}
|
||||
[[ ! -e /$path ]] || printf '%s\0' "$path" >>"$list"
|
||||
}
|
||||
|
||||
# Reproducible model/HF caches are deliberately omitted. Everything below is
|
||||
# either a host configuration, project source, user input or generated result.
|
||||
add_path /etc/mike-ai
|
||||
add_path /opt/mike-ai
|
||||
add_path /var/lib/mike-ai-disaster-backup/latest
|
||||
add_path /data/voice/applio/logs
|
||||
add_path /data/voice/applio/datasets
|
||||
add_path /data/voice/applio/config.json
|
||||
add_path /data/voice/omnivoice/output
|
||||
add_path /data/voice/xvc/output
|
||||
add_path /data/voice/studio
|
||||
add_path /data/music
|
||||
add_path /data/audio
|
||||
add_path /data/llama-dashboard
|
||||
add_path /data/mike-ai-operator
|
||||
add_path /data/benchmarks
|
||||
add_path /data/model-benchmarks
|
||||
add_path /data/image-comparison
|
||||
add_path /data/backups
|
||||
add_path /data/deploy-backups
|
||||
|
||||
log "Portables, verschlüsseltes Backup erzeugen"
|
||||
tar --create --numeric-owner --acls --xattrs -C / --null --files-from="$list" \
|
||||
| zstd -T0 -3 \
|
||||
| age -R "$RECIPIENT_FILE" -o "$partial"
|
||||
chmod 0644 "$partial"
|
||||
mv "$partial" "$target"
|
||||
sha256sum "$target" >"$target.sha256"
|
||||
chmod 0644 "$target.sha256"
|
||||
|
||||
log "Nur die letzten $KEEP Generationen behalten"
|
||||
mapfile -t old < <(find "$OUTPUT_DIR" -maxdepth 1 -type f \
|
||||
-name 'athena-portable-*.tar.zst.age' -printf '%T@ %p\n' | sort -rn | tail -n +$((KEEP + 1)) | cut -d' ' -f2-)
|
||||
for archive in "${old[@]}"; do
|
||||
rm -f -- "$archive" "$archive.sha256"
|
||||
done
|
||||
|
||||
printf 'ATHENA_EXPORT_BACKUP_OK file=%s bytes=%s\n' "$target" "$(stat -c %s "$target")"
|
||||
Reference in New Issue
Block a user