#!/usr/bin/env bash # ============================================================================== # Metatron Student ERP - Production Backup & Recovery Script # Usage: # ./backup_restore.sh backup [DEST_DIR] # ./backup_restore.sh restore # ./backup_restore.sh verify # ============================================================================== set -euo pipefail DB_CONTAINER="${DB_CONTAINER:-metatron_academic_db}" ODOO_CONTAINER="${ODOO_CONTAINER:-metatron_academic}" DB_USER="${POSTGRES_USER:-odoo}" DB_NAME="${POSTGRES_DB:-metatron_aca_erp}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) ACTION="${1:-help}" case "$ACTION" in backup) BACKUP_DIR="${2:-./backups}" mkdir -p "$BACKUP_DIR" DB_FILE="$BACKUP_DIR/${DB_NAME}_${TIMESTAMP}.dump" FS_FILE="$BACKUP_DIR/filestore_${DB_NAME}_${TIMESTAMP}.tar.gz" echo "[+] Starting PostgreSQL database backup for '$DB_NAME'..." docker exec -t "$DB_CONTAINER" pg_dump -U "$DB_USER" -Fc "$DB_NAME" > "$DB_FILE" echo "[✓] Database backup created: $DB_FILE ($(du -h "$DB_FILE" | cut -f1))" echo "[+] Starting Odoo filestore archive for '$DB_NAME'..." docker exec "$ODOO_CONTAINER" tar -czf - -C /var/lib/odoo/filestore "$DB_NAME" > "$FS_FILE" echo "[✓] Filestore archive created: $FS_FILE ($(du -h "$FS_FILE" | cut -f1))" echo "[+] Calculating SHA256 checksums..." if command -v shasum >/dev/null 2>&1; then shasum -a 256 "$DB_FILE" "$FS_FILE" > "$BACKUP_DIR/checksums_${TIMESTAMP}.sha256" elif command -v sha256sum >/dev/null 2>&1; then sha256sum "$DB_FILE" "$FS_FILE" > "$BACKUP_DIR/checksums_${TIMESTAMP}.sha256" fi echo "==================================================================" echo "BACKUP SUCCESSFUL: $TIMESTAMP" echo "Database: $DB_FILE" echo "Filestore: $FS_FILE" echo "==================================================================" ;; verify) DB_FILE="${2:-}" FS_FILE="${3:-}" if [[ -z "$DB_FILE" || -z "$FS_FILE" ]]; then echo "[-] Error: Provide both database dump and filestore archive to verify." echo " Usage: $0 verify " exit 1 fi echo "[+] Verifying database archive integrity..." # pg_restore -l lists table of contents without restoring docker exec -i "$DB_CONTAINER" pg_restore -l < "$DB_FILE" > /dev/null echo "[✓] Database dump archive is valid." echo "[+] Verifying filestore tar.gz integrity..." tar -tzf "$FS_FILE" > /dev/null echo "[✓] Filestore tar.gz archive is valid." echo "All backup archives verified intact." ;; restore) DB_FILE="${2:-}" FS_FILE="${3:-}" TARGET_DB="${4:-${DB_NAME}_restored}" if [[ -z "$DB_FILE" || -z "$FS_FILE" ]]; then echo "[-] Error: Provide DB dump file, filestore archive, and target database name." echo " Usage: $0 restore [TARGET_DB]" exit 1 fi echo "[!] WARNING: You are about to restore to database '$TARGET_DB'." read -p "Are you sure you want to continue? (y/N): " CONFIRM if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then echo "Restore aborted by user." exit 0 fi echo "[+] Creating database '$TARGET_DB' if not exists..." docker exec -i "$DB_CONTAINER" psql -U "$DB_USER" -c "CREATE DATABASE \"$TARGET_DB\" OWNER \"$DB_USER\";" 2>/dev/null || true echo "[+] Restoring PostgreSQL database from $DB_FILE..." docker exec -i "$DB_CONTAINER" pg_restore -U "$DB_USER" -d "$TARGET_DB" --clean --if-exists < "$DB_FILE" || true echo "[✓] Database restore completed." echo "[+] Restoring filestore to container..." docker exec -i "$ODOO_CONTAINER" mkdir -p /var/lib/odoo/filestore/"$TARGET_DB" docker exec -i "$ODOO_CONTAINER" tar -xzf - -C /var/lib/odoo/filestore/"$TARGET_DB" --strip-components=1 < "$FS_FILE" echo "[✓] Filestore restored to /var/lib/odoo/filestore/$TARGET_DB." ;; *) echo "Metatron Student ERP Backup & Recovery Utility" echo "Usage:" echo " $0 backup [DEST_DIR] - Take full DB and filestore backup" echo " $0 verify - Test backup archive integrity" echo " $0 restore - Restore to target database" exit 1 ;; esac