147 lines
3.8 KiB
Bash
147 lines
3.8 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
BACKUP_TARGET="${BACKUP_TARGET:-/backups}"
|
|
BACKUP_PASSWORD="${BACKUP_PASSWORD:-}"
|
|
BACKUP_RETENTION="${BACKUP_RETENTION:-7d}"
|
|
|
|
# Paths to backup
|
|
BACKUP_PATHS=(
|
|
"/data/postgres"
|
|
"/data/redis"
|
|
"/data/duckdb"
|
|
"/data/loki"
|
|
"/data/caddy"
|
|
"/personalities"
|
|
"/workspaces"
|
|
)
|
|
|
|
# Validate password
|
|
if [ -z "$BACKUP_PASSWORD" ]; then
|
|
echo "ERROR: BACKUP_PASSWORD is required"
|
|
exit 1
|
|
fi
|
|
|
|
# Setup restic environment
|
|
export RESTIC_PASSWORD="$BACKUP_PASSWORD"
|
|
export RESTIC_REPOSITORY="$BACKUP_TARGET"
|
|
|
|
# Setup cloud credentials if provided
|
|
[ -n "$BACKUP_S3_ACCESS_KEY" ] && export AWS_ACCESS_KEY_ID="$BACKUP_S3_ACCESS_KEY"
|
|
[ -n "$BACKUP_S3_SECRET_KEY" ] && export AWS_SECRET_ACCESS_KEY="$BACKUP_S3_SECRET_KEY"
|
|
[ -n "$BACKUP_B2_ACCOUNT_ID" ] && export B2_ACCOUNT_ID="$BACKUP_B2_ACCOUNT_ID"
|
|
[ -n "$BACKUP_B2_ACCOUNT_KEY" ] && export B2_ACCOUNT_KEY="$BACKUP_B2_ACCOUNT_KEY"
|
|
|
|
START_TIME=$(date +%s)
|
|
echo "=== VibeStack Backup ==="
|
|
echo "Time: $(date -Iseconds)"
|
|
echo "Target: $BACKUP_TARGET"
|
|
echo ""
|
|
|
|
# Pre-backup: dump PostgreSQL if running
|
|
pre_backup_postgres() {
|
|
if command -v pg_dump &>/dev/null && [ -d "/data/postgres" ]; then
|
|
echo "Creating PostgreSQL dump..."
|
|
|
|
# Source postgres env if available
|
|
[ -f /run/vibestack/postgres.env ] && source /run/vibestack/postgres.env
|
|
|
|
local pg_user="${POSTGRES_USER:-vibestack}"
|
|
local pg_db="${POSTGRES_DB:-vibestack}"
|
|
local dump_file="/data/postgres/backup.sql"
|
|
|
|
if pg_dump -U "$pg_user" -d "$pg_db" -f "$dump_file" 2>/dev/null; then
|
|
echo " PostgreSQL dump created: $dump_file"
|
|
else
|
|
echo " PostgreSQL dump skipped (database not running or accessible)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Pre-backup: trigger Redis BGSAVE if running
|
|
pre_backup_redis() {
|
|
if command -v redis-cli &>/dev/null; then
|
|
echo "Triggering Redis BGSAVE..."
|
|
|
|
# Source redis env if available
|
|
[ -f /run/vibestack/redis.env ] && source /run/vibestack/redis.env
|
|
|
|
local redis_pass="${REDIS_PASSWORD:-}"
|
|
local auth_args=""
|
|
[ -n "$redis_pass" ] && auth_args="-a $redis_pass"
|
|
|
|
if redis-cli $auth_args BGSAVE 2>/dev/null; then
|
|
# Wait for save to complete
|
|
sleep 2
|
|
echo " Redis BGSAVE triggered"
|
|
else
|
|
echo " Redis BGSAVE skipped (not running)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Run pre-backup hooks
|
|
echo "Running pre-backup hooks..."
|
|
pre_backup_postgres
|
|
pre_backup_redis
|
|
echo ""
|
|
|
|
# Build list of paths that exist
|
|
existing_paths=()
|
|
for path in "${BACKUP_PATHS[@]}"; do
|
|
if [ -e "$path" ]; then
|
|
existing_paths+=("$path")
|
|
echo "Including: $path"
|
|
fi
|
|
done
|
|
|
|
# Allow overriding with specific path
|
|
if [ -n "$1" ] && [ -e "$1" ]; then
|
|
existing_paths=("$1")
|
|
echo "Backing up only: $1"
|
|
fi
|
|
|
|
if [ ${#existing_paths[@]} -eq 0 ]; then
|
|
echo "WARNING: No paths to backup"
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo "Starting backup..."
|
|
|
|
# Run restic backup
|
|
BACKUP_OUTPUT=$(restic backup "${existing_paths[@]}" --json 2>&1 | tail -1)
|
|
|
|
# Parse results
|
|
SNAPSHOT_ID=$(echo "$BACKUP_OUTPUT" | jq -r '.snapshot_id // empty' 2>/dev/null || echo "")
|
|
BYTES_ADDED=$(echo "$BACKUP_OUTPUT" | jq -r '.data_added // 0' 2>/dev/null || echo "0")
|
|
|
|
END_TIME=$(date +%s)
|
|
DURATION=$((END_TIME - START_TIME))
|
|
|
|
echo ""
|
|
echo "Backup complete!"
|
|
echo " Snapshot: ${SNAPSHOT_ID:-unknown}"
|
|
echo " Duration: ${DURATION}s"
|
|
echo " Data added: $BYTES_ADDED bytes"
|
|
|
|
# Apply retention policy
|
|
echo ""
|
|
echo "Applying retention policy: keep within $BACKUP_RETENTION..."
|
|
restic forget --keep-within "$BACKUP_RETENTION" --prune
|
|
|
|
# Write status
|
|
cat > /run/vibestack/backup-status.json << EOF
|
|
{
|
|
"status": "idle",
|
|
"last_backup": "$(date -Iseconds)",
|
|
"last_status": "success",
|
|
"snapshot_id": "$SNAPSHOT_ID",
|
|
"duration_seconds": $DURATION,
|
|
"bytes_added": $BYTES_ADDED
|
|
}
|
|
EOF
|
|
|
|
echo ""
|
|
echo "=== Backup Complete ==="
|