#!/bin/bash # Stoatchat Backup Script # Creates a complete backup of the Stoatchat instance including database, files, and configuration set -e # Exit on any error # Configuration BACKUP_DIR="/root/stoatchat-backups" TIMESTAMP=$(date +"%Y%m%d_%H%M%S") BACKUP_NAME="stoatchat_backup_${TIMESTAMP}" BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}" STOATCHAT_DIR="/root/stoatchat" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color log() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" } success() { echo -e "${GREEN}✅ $1${NC}" } warning() { echo -e "${YELLOW}⚠️ $1${NC}" } error() { echo -e "${RED}❌ $1${NC}" exit 1 } # Check if running as root if [[ $EUID -ne 0 ]]; then error "This script must be run as root" fi log "Starting Stoatchat backup process..." log "Backup will be saved to: ${BACKUP_PATH}" # Create backup directory mkdir -p "${BACKUP_PATH}" # 1. Backup MongoDB Database log "Backing up MongoDB database..." if command -v mongodump &> /dev/null; then mongodump --host localhost:27017 --db revolt --out "${BACKUP_PATH}/mongodb" success "MongoDB backup completed" else # Use docker if mongodump not available MONGO_CONTAINER=$(docker ps --format "{{.Names}}" | grep mongo | head -1) if [ ! -z "$MONGO_CONTAINER" ]; then docker exec "$MONGO_CONTAINER" mongodump --db revolt --out /tmp/backup docker cp "$MONGO_CONTAINER:/tmp/backup" "${BACKUP_PATH}/mongodb" success "MongoDB backup completed (via Docker)" else warning "MongoDB backup skipped - no mongodump or mongo container found" fi fi # 2. Backup Configuration Files log "Backing up configuration files..." mkdir -p "${BACKUP_PATH}/config" cp "${STOATCHAT_DIR}/Revolt.toml" "${BACKUP_PATH}/config/" 2>/dev/null || warning "Revolt.toml not found" cp "${STOATCHAT_DIR}/Revolt.overrides.toml" "${BACKUP_PATH}/config/" 2>/dev/null || warning "Revolt.overrides.toml not found" cp "${STOATCHAT_DIR}/compose.yml" "${BACKUP_PATH}/config/" 2>/dev/null || warning "compose.yml not found" cp "${STOATCHAT_DIR}/livekit.yml" "${BACKUP_PATH}/config/" 2>/dev/null || warning "livekit.yml not found" cp "${STOATCHAT_DIR}/manage-services.sh" "${BACKUP_PATH}/config/" 2>/dev/null || warning "manage-services.sh not found" success "Configuration files backed up" # 3. Backup Nginx Configuration log "Backing up Nginx configuration..." mkdir -p "${BACKUP_PATH}/nginx" cp -r /etc/nginx/sites-available/st.vish.gg "${BACKUP_PATH}/nginx/" 2>/dev/null || warning "Nginx site config not found" cp -r /etc/nginx/ssl/ "${BACKUP_PATH}/nginx/" 2>/dev/null || warning "SSL certificates not found" success "Nginx configuration backed up" # 4. Backup User Uploads and Files log "Backing up user uploads and file storage..." mkdir -p "${BACKUP_PATH}/files" # Backup autumn (file server) uploads if they exist if [ -d "${STOATCHAT_DIR}/uploads" ]; then cp -r "${STOATCHAT_DIR}/uploads" "${BACKUP_PATH}/files/" success "User uploads backed up" else warning "No uploads directory found" fi # Check for Docker volume data if docker volume ls | grep -q stoatchat; then log "Backing up Docker volumes..." mkdir -p "${BACKUP_PATH}/docker-volumes" for volume in $(docker volume ls --format "{{.Name}}" | grep stoatchat); do log "Backing up volume: $volume" docker run --rm -v "$volume":/source -v "${BACKUP_PATH}/docker-volumes":/backup alpine tar czf "/backup/${volume}.tar.gz" -C /source . done success "Docker volumes backed up" fi # 5. Backup Environment and System Info log "Backing up system information..." mkdir -p "${BACKUP_PATH}/system" # Save running processes ps aux | grep -E "(revolt|stoatchat|nginx|mongo|redis|livekit)" > "${BACKUP_PATH}/system/processes.txt" 2>/dev/null || true # Save Docker containers docker ps -a > "${BACKUP_PATH}/system/docker-containers.txt" 2>/dev/null || true # Save network configuration ss -tulpn > "${BACKUP_PATH}/system/network-ports.txt" 2>/dev/null || true # Save environment variables (filtered for security) env | grep -E "(REVOLT|STOATCHAT|LIVEKIT)" | grep -v -E "(PASSWORD|SECRET|TOKEN)" > "${BACKUP_PATH}/system/environment.txt" 2>/dev/null || true # Save installed packages dpkg -l > "${BACKUP_PATH}/system/installed-packages.txt" 2>/dev/null || true # Save systemd services systemctl list-units --type=service --state=running > "${BACKUP_PATH}/system/systemd-services.txt" 2>/dev/null || true success "System information backed up" # 6. Create backup metadata log "Creating backup metadata..." cat > "${BACKUP_PATH}/backup-info.txt" << EOF Stoatchat Backup Information ============================ Backup Date: $(date) Backup Name: ${BACKUP_NAME} Source Directory: ${STOATCHAT_DIR} Hostname: $(hostname) OS: $(lsb_release -d 2>/dev/null | cut -f2 || echo "Unknown") Kernel: $(uname -r) Services Status at Backup Time: $(systemctl is-active nginx 2>/dev/null || echo "nginx: unknown") $(docker ps --format "table {{.Names}}\t{{.Status}}" 2>/dev/null || echo "Docker: not available") Git Information: $(cd "${STOATCHAT_DIR}" && git remote -v 2>/dev/null || echo "No git repository") $(cd "${STOATCHAT_DIR}" && git log -1 --oneline 2>/dev/null || echo "No git history") Backup Contents: - MongoDB database (revolt) - Configuration files (Revolt.toml, Revolt.overrides.toml, compose.yml, etc.) - Nginx configuration and SSL certificates - User uploads and file storage - Docker volumes - System information and process list EOF success "Backup metadata created" # 7. Create compressed archive log "Creating compressed archive..." cd "${BACKUP_DIR}" tar -czf "${BACKUP_NAME}.tar.gz" "${BACKUP_NAME}/" ARCHIVE_SIZE=$(du -h "${BACKUP_NAME}.tar.gz" | cut -f1) success "Compressed archive created: ${BACKUP_NAME}.tar.gz (${ARCHIVE_SIZE})" # 8. Cleanup old backups (keep last 7 days) log "Cleaning up old backups (keeping last 7 days)..." find "${BACKUP_DIR}" -name "stoatchat_backup_*.tar.gz" -mtime +7 -delete 2>/dev/null || true find "${BACKUP_DIR}" -name "stoatchat_backup_*" -type d -mtime +7 -exec rm -rf {} + 2>/dev/null || true success "Old backups cleaned up" # 9. Verify backup integrity log "Verifying backup integrity..." if tar -tzf "${BACKUP_NAME}.tar.gz" >/dev/null 2>&1; then success "Backup archive integrity verified" else error "Backup archive is corrupted!" fi # Final summary echo echo "==================================================" echo -e "${GREEN}🎉 BACKUP COMPLETED SUCCESSFULLY! 🎉${NC}" echo "==================================================" echo "Backup Location: ${BACKUP_PATH}.tar.gz" echo "Backup Size: ${ARCHIVE_SIZE}" echo "Backup Contains:" echo " ✅ MongoDB database" echo " ✅ Configuration files" echo " ✅ Nginx configuration & SSL certificates" echo " ✅ User uploads & file storage" echo " ✅ Docker volumes" echo " ✅ System information" echo echo "To restore this backup on a new machine:" echo " 1. Extract: tar -xzf ${BACKUP_NAME}.tar.gz" echo " 2. Follow the deployment guide in DEPLOYMENT.md" echo " 3. Run the restore script: ./restore.sh ${BACKUP_NAME}" echo echo "Backup completed at: $(date)" echo "=================================================="