backup.sh•8.98 kB
#!/bin/bash
################################################################################
# Backup Script for KYC MCP Server
# This script backs up application data, Redis data, and configurations
################################################################################
set -euo pipefail
# Configuration
APP_DIR="/opt/kyc-mcp-server"
BACKUP_BASE_DIR="/opt/kyc-mcp-server-backups"
S3_BUCKET="${S3_BACKUP_BUCKET:-}"
RETENTION_DAYS=30
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_BASE_DIR/backup_$TIMESTAMP"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_step() {
echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
# Error handler
error_exit() {
log_error "$1"
exit 1
}
# Check prerequisites
check_prerequisites() {
log_step "Checking prerequisites..."
if [ ! -d "$APP_DIR" ]; then
error_exit "Application directory not found: $APP_DIR"
fi
if ! command -v docker &> /dev/null; then
error_exit "Docker is not installed"
fi
log_info "Prerequisites check passed"
}
# Create backup directory
create_backup_dir() {
log_step "Creating backup directory..."
mkdir -p "$BACKUP_DIR"
mkdir -p "$BACKUP_DIR/redis"
mkdir -p "$BACKUP_DIR/config"
mkdir -p "$BACKUP_DIR/logs"
mkdir -p "$BACKUP_DIR/docker"
log_info "Backup directory created: $BACKUP_DIR"
}
# Backup Redis data
backup_redis() {
log_step "Backing up Redis data..."
if docker ps | grep -q kyc-redis; then
# Trigger Redis save
docker exec kyc-redis redis-cli SAVE || log_warn "Redis SAVE command failed"
# Copy Redis dump file
docker cp kyc-redis:/data/dump.rdb "$BACKUP_DIR/redis/dump.rdb" 2>/dev/null || log_warn "Failed to copy Redis dump"
# Copy Redis AOF file if exists
docker cp kyc-redis:/data/appendonly.aof "$BACKUP_DIR/redis/appendonly.aof" 2>/dev/null || log_warn "No AOF file found"
log_info "Redis data backed up"
else
log_warn "Redis container not running, skipping Redis backup"
fi
}
# Backup configuration files
backup_config() {
log_step "Backing up configuration files..."
# Backup .env file
if [ -f "$APP_DIR/.env" ]; then
cp "$APP_DIR/.env" "$BACKUP_DIR/config/.env"
log_info "Environment file backed up"
else
log_warn "No .env file found"
fi
# Backup docker-compose.yml
if [ -f "$APP_DIR/docker-compose.yml" ]; then
cp "$APP_DIR/docker-compose.yml" "$BACKUP_DIR/config/docker-compose.yml"
log_info "Docker Compose file backed up"
fi
# Backup nginx configuration if exists
if [ -f /etc/nginx/sites-available/kyc-mcp.conf ]; then
cp /etc/nginx/sites-available/kyc-mcp.conf "$BACKUP_DIR/config/nginx-kyc-mcp.conf"
log_info "Nginx configuration backed up"
fi
# Backup systemd service file if exists
if [ -f /etc/systemd/system/kyc-mcp.service ]; then
cp /etc/systemd/system/kyc-mcp.service "$BACKUP_DIR/config/kyc-mcp.service"
log_info "Systemd service file backed up"
fi
}
# Backup application logs
backup_logs() {
log_step "Backing up application logs..."
if [ -d /var/log/kyc-mcp-server ]; then
cp -r /var/log/kyc-mcp-server/* "$BACKUP_DIR/logs/" 2>/dev/null || log_warn "No logs found"
log_info "Application logs backed up"
else
log_warn "Log directory not found"
fi
# Backup nginx logs
if [ -f /var/log/nginx/kyc-mcp-access.log ]; then
cp /var/log/nginx/kyc-mcp-access.log "$BACKUP_DIR/logs/nginx-access.log"
fi
if [ -f /var/log/nginx/kyc-mcp-error.log ]; then
cp /var/log/nginx/kyc-mcp-error.log "$BACKUP_DIR/logs/nginx-error.log"
fi
}
# Backup Docker images
backup_docker_images() {
log_step "Backing up Docker images..."
if docker images | grep -q kyc-mcp-server; then
docker save kyc-mcp-server:latest -o "$BACKUP_DIR/docker/kyc-mcp-server.tar"
log_info "Docker image backed up"
else
log_warn "Docker image not found"
fi
}
# Create backup metadata
create_metadata() {
log_step "Creating backup metadata..."
cat > "$BACKUP_DIR/metadata.json" <<EOF
{
"backup_timestamp": "$TIMESTAMP",
"backup_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"hostname": "$(hostname)",
"app_version": "$(cd $APP_DIR && git describe --tags 2>/dev/null || echo 'unknown')",
"git_commit": "$(cd $APP_DIR && git rev-parse HEAD 2>/dev/null || echo 'unknown')",
"backup_size": "$(du -sh $BACKUP_DIR | cut -f1)",
"components": {
"redis": $([ -f "$BACKUP_DIR/redis/dump.rdb" ] && echo "true" || echo "false"),
"config": $([ -f "$BACKUP_DIR/config/.env" ] && echo "true" || echo "false"),
"logs": $([ -d "$BACKUP_DIR/logs" ] && echo "true" || echo "false"),
"docker": $([ -f "$BACKUP_DIR/docker/kyc-mcp-server.tar" ] && echo "true" || echo "false")
}
}
EOF
log_info "Backup metadata created"
}
# Compress backup
compress_backup() {
log_step "Compressing backup..."
cd "$BACKUP_BASE_DIR"
tar -czf "backup_$TIMESTAMP.tar.gz" "backup_$TIMESTAMP"
# Remove uncompressed directory
rm -rf "backup_$TIMESTAMP"
BACKUP_FILE="$BACKUP_BASE_DIR/backup_$TIMESTAMP.tar.gz"
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
log_info "Backup compressed: $BACKUP_FILE ($BACKUP_SIZE)"
}
# Upload to S3
upload_to_s3() {
if [ -z "$S3_BUCKET" ]; then
log_warn "S3_BACKUP_BUCKET not set, skipping S3 upload"
return 0
fi
log_step "Uploading backup to S3..."
if ! command -v aws &> /dev/null; then
log_warn "AWS CLI not installed, skipping S3 upload"
return 0
fi
BACKUP_FILE="$BACKUP_BASE_DIR/backup_$TIMESTAMP.tar.gz"
S3_PATH="s3://$S3_BUCKET/kyc-mcp-server/backups/backup_$TIMESTAMP.tar.gz"
if aws s3 cp "$BACKUP_FILE" "$S3_PATH"; then
log_info "Backup uploaded to S3: $S3_PATH"
else
log_error "Failed to upload backup to S3"
return 1
fi
}
# Cleanup old backups
cleanup_old_backups() {
log_step "Cleaning up old backups..."
# Local cleanup
find "$BACKUP_BASE_DIR" -name "backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS -delete
log_info "Deleted local backups older than $RETENTION_DAYS days"
# S3 cleanup
if [ -n "$S3_BUCKET" ] && command -v aws &> /dev/null; then
CUTOFF_DATE=$(date -d "$RETENTION_DAYS days ago" +%Y-%m-%d)
aws s3 ls "s3://$S3_BUCKET/kyc-mcp-server/backups/" | while read -r line; do
BACKUP_DATE=$(echo "$line" | awk '{print $1}')
BACKUP_FILE=$(echo "$line" | awk '{print $4}')
if [[ "$BACKUP_DATE" < "$CUTOFF_DATE" ]]; then
aws s3 rm "s3://$S3_BUCKET/kyc-mcp-server/backups/$BACKUP_FILE"
log_info "Deleted S3 backup: $BACKUP_FILE"
fi
done
fi
}
# Generate backup report
generate_report() {
log_step "Generating backup report..."
BACKUP_FILE="$BACKUP_BASE_DIR/backup_$TIMESTAMP.tar.gz"
cat > "$BACKUP_BASE_DIR/backup_report_$TIMESTAMP.txt" <<EOF
========================================
KYC MCP Server Backup Report
========================================
Backup Timestamp: $TIMESTAMP
Backup Date: $(date)
Hostname: $(hostname)
Backup Details:
- Backup File: $BACKUP_FILE
- Backup Size: $(du -h "$BACKUP_FILE" | cut -f1)
- Components:
* Redis Data: $([ -f "$BACKUP_DIR/redis/dump.rdb" ] && echo "✓" || echo "✗")
* Configuration: $([ -f "$BACKUP_DIR/config/.env" ] && echo "✓" || echo "✗")
* Logs: $([ -d "$BACKUP_DIR/logs" ] && echo "✓" || echo "✗")
* Docker Image: $([ -f "$BACKUP_DIR/docker/kyc-mcp-server.tar" ] && echo "✓" || echo "✗")
S3 Upload: $([ -n "$S3_BUCKET" ] && echo "Enabled" || echo "Disabled")
$([ -n "$S3_BUCKET" ] && echo "S3 Bucket: $S3_BUCKET" || echo "")
Retention Policy: $RETENTION_DAYS days
========================================
EOF
cat "$BACKUP_BASE_DIR/backup_report_$TIMESTAMP.txt"
}
# Main backup function
main() {
log_info "Starting backup of KYC MCP Server..."
check_prerequisites
create_backup_dir
backup_redis
backup_config
backup_logs
backup_docker_images
create_metadata
compress_backup
upload_to_s3
cleanup_old_backups
generate_report
log_info "=========================================="
log_info "Backup completed successfully!"
log_info "=========================================="
}
# Run main function
main