#!/bin/bash # root-essentials-backup.sh — Daily backup of Hermes config/core to S3 # Small tarball (42MB): configs, scripts, skills, references, SSH keys # Excludes state.db (covered by live sync every 15 min) set -euo pipefail DATE=$(date +%F) BACKUP_FILE="/tmp/root-essentials-${DATE}.tar.gz" ENDPOINT="https://s3.us-east-1.wasabisys.com" BUCKET="hermes-vps-backups" PREFIX="root-backup" if [ -f /opt/awscli-venv/bin/activate ]; then source /opt/awscli-venv/bin/activate fi echo "[$(date)] Creating backup..." cd /root tar czf "$BACKUP_FILE" \ .hermes/config.yaml .hermes/.env .hermes/skills .hermes/scripts .hermes/references \ .hermes/profiles .hermes/cron .hermes/memories .hermes/DR-PLAN.md \ .hermes/data .hermes/cache/delegation \ .ssh .aws .config/himalaya \ shark-game projects \ --exclude='*.db' --exclude='*.db-shm' --exclude='*.db-wal' 2>/dev/null # Add system-level configs tar --append --file="$BACKUP_FILE" \ -C /etc systemd/system/caddy/Caddyfile 2>/dev/null || true tar --append --file="$BACKUP_FILE" \ -C /var www 2>/dev/null || true SIZE=$(stat -c%s "$BACKUP_FILE" 2>/dev/null || echo 0) echo "[$(date)] Tarball: ${SIZE} bytes" # Upload echo "[$(date)] Uploading..." aws s3 cp "$BACKUP_FILE" "s3://${BUCKET}/${PREFIX}/root-essentials-${DATE}.tar.gz" \ --endpoint-url "$ENDPOINT" 2>&1 # Verify — download and test integrity echo "[$(date)] Verifying integrity..." aws s3 cp "s3://${BUCKET}/${PREFIX}/root-essentials-${DATE}.tar.gz" \ /tmp/root-verify.tar.gz --endpoint-url "$ENDPOINT" --quiet 2>&1 if tar tzf /tmp/root-verify.tar.gz > /dev/null 2>&1; then echo "[$(date)] ✅ Backup verified — archive is valid" rm /tmp/root-verify.tar.gz else echo "[$(date)] ❌ BACKUP CORRUPT — verification failed!" exit 1 fi # Cleanup rm "$BACKUP_FILE" echo "[$(date)] Done"