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>
This commit is contained in:
89
backup-sovereign/scripts/10_backup_plan.sh
Executable file
89
backup-sovereign/scripts/10_backup_plan.sh
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user