#!/bin/bash # ============================================================================= # LetsBe Backup Script # ============================================================================= # Backs up Docker volumes and databases to configured rclone remote # Configure rclone first: rclone config # ============================================================================= set -euo pipefail BACKUP_DIR="/tmp/letsbe-backups" DATE=$(date +%Y%m%d_%H%M%S) RCLONE_REMOTE="remote" # Configure this in rclone config # Create backup directory mkdir -p "$BACKUP_DIR" echo "=== LetsBe Backup - $DATE ===" # Function to backup a postgres database backup_postgres() { local container=$1 local db_name=$2 local db_user=${3:-postgres} if docker ps --format '{{.Names}}' | grep -q "^${container}$"; then echo "Backing up PostgreSQL: $container ($db_name)..." docker exec "$container" pg_dump -U "$db_user" "$db_name" | gzip > "$BACKUP_DIR/${container}_${DATE}.sql.gz" fi } # Function to backup a mysql database backup_mysql() { local container=$1 local db_name=$2 local db_user=${3:-root} local db_pass=$4 if docker ps --format '{{.Names}}' | grep -q "^${container}$"; then echo "Backing up MySQL: $container ($db_name)..." docker exec "$container" mysqldump -u"$db_user" -p"$db_pass" "$db_name" | gzip > "$BACKUP_DIR/${container}_${DATE}.sql.gz" fi } # Function to backup docker volumes backup_volume() { local volume=$1 if docker volume ls --format '{{.Name}}' | grep -q "^${volume}$"; then echo "Backing up volume: $volume..." docker run --rm -v "${volume}:/data" -v "$BACKUP_DIR:/backup" alpine tar czf "/backup/${volume}_${DATE}.tar.gz" -C /data . fi } # ============================================================================= # BACKUP DATABASES # ============================================================================= # Chatwoot backup_postgres "*-chatwoot-postgres" "chatwoot_production" "chatwoot" 2>/dev/null || true # NoCoDB backup_postgres "*-nocodb-postgres" "nocodb" "postgres" 2>/dev/null || true # Baserow backup_postgres "*-baserow-db" "baserow" "baserow" 2>/dev/null || true # n8n backup_postgres "*-n8n-postgres" "n8n" "n8n" 2>/dev/null || true # Nextcloud backup_postgres "*-nextcloud-postgres" "nextcloud" "nextcloud" 2>/dev/null || true # Typebot backup_postgres "*-typebot-db" "typebot" "postgres" 2>/dev/null || true # ============================================================================= # BACKUP VOLUMES (important data) # ============================================================================= # Get all letsbe-related volumes for vol in $(docker volume ls --format '{{.Name}}' | grep -E '(storage|data|uploads)'); do backup_volume "$vol" 2>/dev/null || true done # ============================================================================= # UPLOAD TO REMOTE # ============================================================================= if command -v rclone &> /dev/null; then if rclone listremotes | grep -q "^${RCLONE_REMOTE}:"; then echo "Uploading backups to $RCLONE_REMOTE..." rclone copy "$BACKUP_DIR" "${RCLONE_REMOTE}:letsbe-backups/${DATE}/" --progress echo "Upload complete." else echo "WARNING: rclone remote '$RCLONE_REMOTE' not configured. Backups stored locally only." fi else echo "WARNING: rclone not installed. Backups stored locally only." fi # ============================================================================= # CLEANUP OLD LOCAL BACKUPS (keep last 7 days) # ============================================================================= find "$BACKUP_DIR" -type f -mtime +7 -delete 2>/dev/null || true echo "=== Backup Complete ===" echo "Local backups: $BACKUP_DIR"