R510 -> R730XD/Proxmox migration helpers (consistent DB dumps, B2/Kopia snapshot refresh, cutover final backup) plus the previously-untracked gitea-portainer-registry cutover plan under docs/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
3.4 KiB
Bash
58 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# CUTOVER final backup — valhalla R510 (run as ginnoir, right before zpool export).
|
|
#
|
|
# Takes the FINAL consistent backup of everything not already on the pool, lands it on
|
|
# /storage1 (which travels with the disks), then leaves all services STOPPED.
|
|
# Does NOT restart services and does NOT export the pool (that's a separate confirmed step).
|
|
#
|
|
# Order matters: dump DBs while their containers are still up, THEN stop everything, THEN
|
|
# tar /config (consistent), THEN stop Plex + delta-rsync it.
|
|
#
|
|
set -uo pipefail
|
|
DEST=/storage1/migration-backup
|
|
STAMP=$(date +%Y%m%d-%H%M%S)
|
|
OUT="$DEST/cutover-$STAMP"
|
|
mkdir -p "$OUT/db" "$OUT/config"
|
|
LOG="$OUT/cutover.log"; exec > >(tee -a "$LOG") 2>&1
|
|
log(){ printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; }
|
|
running(){ docker ps --format '{{.Names}}' | grep -qx "$1"; }
|
|
pg_super(){ local c="$1" cand; for cand in "$(docker exec "$c" printenv POSTGRES_USER 2>/dev/null)" immich postgres; do [ -z "$cand" ] && continue; docker exec "$c" psql -U "$cand" -tAc 'select 1' >/dev/null 2>&1 && { echo "$cand"; return 0; }; done; return 1; }
|
|
|
|
log "===== CUTOVER FINAL BACKUP -> $OUT ====="
|
|
|
|
# --- 1. dump all databases (containers still running) ---
|
|
for c in postgres_authentik postgres_famapp postgres_gitea postgres_plane postgres_resume nextcloud-postgres immich-postgres; do
|
|
running "$c" || { log "skip $c (down)"; continue; }
|
|
if u=$(pg_super "$c"); then
|
|
docker exec "$c" pg_dumpall --clean --if-exists -U "$u" | gzip > "$OUT/db/$c.sql.gz" && log "pg $c (u=$u) ok" || { log "WARN pg $c failed"; rm -f "$OUT/db/$c.sql.gz"; }
|
|
else log "WARN no superuser for $c"; fi
|
|
done
|
|
# owncloud + romm: root w/ env password, named DB
|
|
dump_maria_pw(){ local c="$1" db="$2" pw; pw=$(docker exec "$c" sh -c 'printf %s "${MARIADB_ROOT_PASSWORD:-${MYSQL_ROOT_PASSWORD:-}}"' 2>/dev/null); docker exec -e MYSQL_PWD="$pw" "$c" mariadb-dump -uroot --single-transaction --routines --triggers "$db" 2>/dev/null | gzip > "$OUT/db/$c.sql.gz" && log "maria $c ok" || { log "WARN maria $c failed"; rm -f "$OUT/db/$c.sql.gz"; }; }
|
|
running owncloud_mariadb && dump_maria_pw owncloud_mariadb owncloud
|
|
running romm-db && dump_maria_pw romm-db romm
|
|
# bookstack: root via unix_socket, all DBs
|
|
running mariadb_bookstack && { docker exec mariadb_bookstack mariadb-dump -uroot --single-transaction --all-databases 2>/dev/null | gzip > "$OUT/db/mariadb_bookstack.sql.gz" && log "maria bookstack ok" || log "WARN bookstack failed"; }
|
|
log "db dumps:"; ls -lh "$OUT/db"
|
|
|
|
# --- 2. stop ALL containers (homelab goes down) ---
|
|
log "stopping all containers..."
|
|
docker stop $(docker ps -q) >/dev/null 2>&1; sleep 2
|
|
log "running containers now: $(docker ps -q | wc -l) (expect 0)"
|
|
|
|
# --- 3. tar /config (now fully consistent) ---
|
|
log "tar /config (~112G, the long step)"
|
|
sudo tar --warning=no-file-changed -cf "$OUT/config/config.tar" -C / config && log "config.tar done" || log "WARN config tar non-zero"
|
|
|
|
# --- 4. Plex: stop + final delta rsync ---
|
|
log "stopping Plex + final delta rsync"
|
|
sudo systemctl stop plexmediaserver
|
|
sudo rsync -aHX "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server" /storage1/labdata/plex/ && log "plex delta synced" || log "WARN plex rsync"
|
|
|
|
# --- 5. checksums + sizes ---
|
|
log "checksums"
|
|
( cd "$OUT" && find . -type f ! -name SHA256SUMS -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS )
|
|
du -sh "$OUT"/db "$OUT"/config 2>/dev/null
|
|
log "===== CUTOVER BACKUP COMPLETE. Services stopped. Ready to release /storage1 + export. ====="
|