Files
vm-skills/backup-sovereign/scripts/10_backup_plan.sh
Vault Sovereign eac77ef7b4 Initial commit: VaultMesh Skills collection
Collection of operational skills for VaultMesh infrastructure including:
- backup-sovereign: Backup and recovery operations
- btc-anchor: Bitcoin anchoring
- cloudflare-tunnel-manager: Cloudflare tunnel management
- container-registry: Container registry operations
- disaster-recovery: Disaster recovery procedures
- dns-sovereign: DNS management
- eth-anchor: Ethereum anchoring
- gitea-bootstrap: Gitea setup and configuration
- hetzner-bootstrap: Hetzner server provisioning
- merkle-forest: Merkle tree operations
- node-hardening: Node security hardening
- operator-bootstrap: Operator initialization
- proof-verifier: Cryptographic proof verification
- rfc3161-anchor: RFC3161 timestamping
- secrets-vault: Secrets management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 00:25:00 +00:00

90 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# === METADATA ===
SCRIPT_NAME="$(basename "$0")"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
# === CONFIGURATION ===
: "${NODE_NAME:=node-a}"
: "${BACKUP_LABEL:=manual}"
: "${OUTPUT_DIR:=$SKILL_ROOT/outputs}"
: "${BACKUP_SOURCES:=}"
: "${BACKUP_EXCLUDES:=.git,node_modules,target,dist,outputs}"
# === FUNCTIONS ===
log_plan() { echo "[PLAN] $(date -Iseconds) $*"; }
die() { echo "[ERROR] $(date -Iseconds) $*" >&2; exit 1; }
estimate_size() {
local total=0
IFS=',' read -r -a sources <<< "$BACKUP_SOURCES"
IFS=',' read -r -a excludes <<< "$BACKUP_EXCLUDES"
for src in "${sources[@]}"; do
src="${src/#\~/$HOME}"
if [[ -e "$src" ]]; then
# Build find exclude args
local find_excludes=()
for ex in "${excludes[@]}"; do
find_excludes+=(-name "$ex" -prune -o)
done
local size
size=$(find "$src" "${find_excludes[@]}" -type f -print0 2>/dev/null | \
xargs -0 stat -c%s 2>/dev/null | \
awk '{sum+=$1} END {print sum+0}')
total=$((total + size))
fi
done
echo "$total"
}
main() {
[[ -n "$BACKUP_SOURCES" ]] || die "BACKUP_SOURCES is required (comma-separated paths)."
local ts run_id run_dir
ts="$(date -Iseconds | tr ':' '-')"
run_id="${NODE_NAME}_${BACKUP_LABEL}_${ts}"
run_dir="$OUTPUT_DIR/runs/$run_id"
log_plan "=== Backup Plan ==="
log_plan "Run ID: $run_id"
log_plan "Run directory: $run_dir"
log_plan "Archive: $run_dir/archive.tar.gz"
log_plan "Manifest: $run_dir/manifest.json"
echo ""
log_plan "=== Sources ==="
IFS=',' read -r -a sources <<< "$BACKUP_SOURCES"
for src in "${sources[@]}"; do
src="${src/#\~/$HOME}"
if [[ -e "$src" ]]; then
log_plan " [OK] $src"
else
log_plan " [MISSING] $src"
fi
done
echo ""
log_plan "=== Excludes ==="
IFS=',' read -r -a excludes <<< "$BACKUP_EXCLUDES"
for ex in "${excludes[@]}"; do
log_plan " - $ex"
done
echo ""
log_plan "=== Size Estimate ==="
local est_bytes est_mb
est_bytes=$(estimate_size)
est_mb=$((est_bytes / 1024 / 1024))
log_plan "Estimated uncompressed: ${est_mb} MB ($est_bytes bytes)"
log_plan "Compressed size will be smaller (typically 30-70% of original)"
echo ""
log_plan "Next: ./scripts/11_backup_apply.sh (requires DRY_RUN=0)"
}
[[ "${BASH_SOURCE[0]}" == "$0" ]] && main "$@"