name: Backup MinIO Buckets on: schedule: # Run daily at 2 AM - cron: '0 2 * * *' workflow_dispatch: jobs: backup: runs-on: ubuntu-latest container: image: catthehacker/ubuntu:act-latest steps: # 1๏ธโƒฃ Setup SSH - name: Setup SSH shell: sh env: DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | mkdir -p ~/.ssh chmod 700 ~/.ssh echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts # 2๏ธโƒฃ Run backup on server - name: Backup MinIO buckets shell: sh env: DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | ssh -i ~/.ssh/id_ed25519 $DEPLOY_USER@$DEPLOY_HOST << 'EOF' set -e BACKUP_BASE="/var/backups/minio" BACKUP_DIR="$BACKUP_BASE/$(date +%Y%m%d_%H%M%S)" CONTAINER_NAME="crew-minio-prod" DEPLOY_DIR="/var/www/apps/minio-storage" echo "๐Ÿ“ฆ Starting MinIO backup to $BACKUP_DIR" sudo mkdir -p "$BACKUP_DIR" sudo chown $USER:$USER "$BACKUP_DIR" # Check if container is running if ! docker ps --format '{{.Names}}' | grep -q "$CONTAINER_NAME"; then echo "โŒ MinIO container is not running" exit 1 fi # Load credentials from .env file echo "๐Ÿ”‘ Loading MinIO credentials" if [ ! -f "$DEPLOY_DIR/.env" ]; then echo "โŒ .env file not found at $DEPLOY_DIR/.env" exit 1 fi # Source .env and export variables set -a source "$DEPLOY_DIR/.env" set +a if [ -z "$MINIO_ROOT_USER" ] || [ -z "$MINIO_ROOT_PASSWORD" ]; then echo "โŒ MINIO_ROOT_USER or MINIO_ROOT_PASSWORD not set in .env" exit 1 fi echo "โœ“ Credentials loaded (User: $MINIO_ROOT_USER)" echo "๐Ÿ”ง Installing MinIO client if needed" docker exec $CONTAINER_NAME sh -c " if ! command -v mc &> /dev/null; then curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc chmod +x /usr/local/bin/mc fi " || echo "mc already installed" echo "โš™๏ธ Configuring MinIO client" docker exec $CONTAINER_NAME mc alias set backup http://localhost:9000 \ "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" # Backup each bucket BUCKETS="crewsportswear merchbay merchbay-admin crew-admin email-reports" for BUCKET in $BUCKETS; do echo "๐Ÿ’พ Backing up bucket: $BUCKET" # Create bucket directory sudo mkdir -p "$BACKUP_DIR/$BUCKET" sudo chown $USER:$USER "$BACKUP_DIR/$BUCKET" # Export bucket to container temp docker exec $CONTAINER_NAME mc mirror --overwrite backup/$BUCKET /tmp/backup_$BUCKET/ # Copy from container to host docker cp $CONTAINER_NAME:/tmp/backup_$BUCKET/. "$BACKUP_DIR/$BUCKET/" # Cleanup container temp docker exec $CONTAINER_NAME rm -rf /tmp/backup_$BUCKET # Count files FILE_COUNT=$(find "$BACKUP_DIR/$BUCKET" -type f | wc -l) echo " โœ“ Backed up $FILE_COUNT files from $BUCKET" done echo "๐Ÿ“Š Backup statistics" du -sh "$BACKUP_DIR" du -sh "$BACKUP_DIR"/* echo "๐Ÿ—œ๏ธ Compressing backup" cd "$BACKUP_BASE" tar -czf "minio_backup_$(date +%Y%m%d_%H%M%S).tar.gz" "$(basename $BACKUP_DIR)" echo "๐Ÿงน Removing uncompressed backup" rm -rf "$BACKUP_DIR" echo "๐Ÿ—‘๏ธ Cleaning old backups (keeping last 7 days)" find "$BACKUP_BASE" -name "minio_backup_*.tar.gz" -type f -mtime +7 -delete echo "๐Ÿ“‹ Current backups:" ls -lh "$BACKUP_BASE"/minio_backup_*.tar.gz 2>/dev/null || echo "No compressed backups found" echo "โœ… Backup completed successfully!" EOF # 3๏ธโƒฃ Verify backup - name: Verify backup shell: sh env: DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | ssh -i ~/.ssh/id_ed25519 $DEPLOY_USER@$DEPLOY_HOST << 'EOF' LATEST_BACKUP=$(ls -t /var/backups/minio/minio_backup_*.tar.gz 2>/dev/null | head -1) if [ -f "$LATEST_BACKUP" ]; then echo "โœ… Latest backup verified:" ls -lh "$LATEST_BACKUP" BACKUP_SIZE=$(du -sh "$LATEST_BACKUP" | awk '{print $1}') echo "๐Ÿ“ฆ Backup size: $BACKUP_SIZE" else echo "โŒ No backup file found!" exit 1 fi EOF