Резервное копирование Evolution API
Описание системы
Evolution API - это система для работы с WhatsApp Business API, развернутая в Docker контейнерах. Система состоит из:
- evolution-api - основное приложение API
- evolution_postgres - база данных PostgreSQL 15
- redis - кэш и хранилище сессий
<note important> Данная инструкция предназначена для систем с Evolution API, развернутой через Docker Compose в директории `/opt/evolution-api/`. </note>
Компоненты для резервного копирования
Скрипт создает резервные копии следующих компонентов:
| Компонент | Описание | Расположение |
|---|---|---|
| store/ | Файлы и медиа сообщений | `/opt/evolution-api/store/` |
| instances/ | Конфигурации инстансов WhatsApp | `/opt/evolution-api/instances/` |
| postgres_data/ | Физические файлы базы данных | `/opt/evolution-api/postgres_data/` |
| redis_data/ | Данные Redis кэша | `/opt/evolution-api/redis_data/` |
| docker-compose.yml | Конфигурация контейнеров | `/opt/evolution-api/docker-compose.yml` |
| database.sql | SQL дамп базы данных | Создается автоматически |
Требования
Системные требования
- OS: Linux (тестировано на Ubuntu 20.04+)
- Docker: версия 20.10+
- Docker Compose: версия 1.29+
- Свободное место: минимум 2GB для бекапов
- Права: root или пользователь в группе docker
Необходимые пакеты
# Ubuntu/Debian apt update && apt install -y curl tar gzip findutils # CentOS/RHEL yum install -y curl tar gzip findutils
Установка и настройка
1. Создание структуры директорий
# Создаем директории для скриптов и бекапов mkdir -p /opt/scripts mkdir -p /opt/backups/evolution-api # Устанавливаем права доступа chmod 750 /opt/scripts chmod 750 /opt/backups/evolution-api
2. Установка скрипта
Создайте файл `/opt/scripts/evolution-backup.sh` и вставьте содержимое скрипта ниже.
# Создаем скрипт nano /opt/scripts/evolution-backup.sh # Делаем исполняемым chmod +x /opt/scripts/evolution-backup.sh # Устанавливаем владельца (если нужно) chown root:root /opt/scripts/evolution-backup.sh
Содержимое скрипта `/opt/scripts/evolution-backup.sh`:
#!/bin/bash # Скрипт резервного копирования Evolution API # Запуск: /opt/scripts/evolution-backup.sh # Настройки COMPOSE_FILE="/opt/evolution-api/docker-compose.yml" EVOLUTION_DIR="/opt/evolution-api" BACKUP_DIR="/opt/backups/evolution-api" DATE=$(date +"%Y%m%d_%H%M%S") BACKUP_NAME="evolution_backup_${DATE}" RETENTION_DAYS=10 # Храним бекапы 10 дней # Настройки базы данных DB_CONTAINER="evolution_postgres" DB_USER="evolution_user" DB_PASSWORD="ВАШ_ПАРОЛЬ_БД" # ⚠️ Замените на реальный пароль! DB_NAME="evolution_db" # Логирование LOG_FILE="${BACKUP_DIR}/backup.log" # Функция логирования log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } # Создаем директорию для бекапов если не существует mkdir -p "$BACKUP_DIR" log "=== Начало резервного копирования Evolution API ===" # Проверяем что compose файл существует if [ ! -f "$COMPOSE_FILE" ]; then log "ОШИБКА: Файл $COMPOSE_FILE не найден!" exit 1 fi # Переходим в директорию с Evolution cd "$EVOLUTION_DIR" || { log "ОШИБКА: Не удалось перейти в директорию $EVOLUTION_DIR" exit 1 } # Проверяем что контейнеры запущены log "Проверяем статус контейнеров..." if ! docker-compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then log "ОШИБКА: Контейнеры не запущены! Запустите их перед созданием бекапа." exit 1 fi # Создаем дамп базы данных (пока контейнеры работают) log "Создаем дамп базы данных..." DB_DUMP_PATH="${BACKUP_DIR}/${BACKUP_NAME}_database.sql" # Экспортируем пароль для pg_dump export PGPASSWORD="$DB_PASSWORD" docker exec "$DB_CONTAINER" pg_dump -U "$DB_USER" -d "$DB_NAME" --no-password --verbose > "$DB_DUMP_PATH" 2>> "$LOG_FILE" if [ $? -eq 0 ] && [ -s "$DB_DUMP_PATH" ]; then log "Дамп базы данных создан: $DB_DUMP_PATH" # Получаем размер дампа DB_DUMP_SIZE=$(du -h "$DB_DUMP_PATH" | cut -f1) log "Размер дампа БД: $DB_DUMP_SIZE" else log "ОШИБКА: Не удалось создать дамп базы данных или файл пуст" rm -f "$DB_DUMP_PATH" exit 1 fi # Очищаем переменную окружения unset PGPASSWORD # Останавливаем контейнеры log "Останавливаем контейнеры Evolution API..." docker-compose -f "$COMPOSE_FILE" down if [ $? -eq 0 ]; then log "Контейнеры успешно остановлены" else log "ОШИБКА: Не удалось остановить контейнеры" exit 1 fi # Ждем пару секунд для полной остановки sleep 5 # Создаем архив с данными (включая дамп БД) log "Создаем архив данных..." BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" tar -czf "$BACKUP_PATH" \ --exclude='*.log' \ --exclude='**/lost+found' \ -C "$BACKUP_DIR" "${BACKUP_NAME}_database.sql" \ -C "$EVOLUTION_DIR" \ store/ \ instances/ \ postgres_data/ \ redis_data/ \ docker-compose.yml if [ $? -eq 0 ]; then log "Архив создан: $BACKUP_PATH" # Получаем размер архива BACKUP_SIZE=$(du -h "$BACKUP_PATH" | cut -f1) log "Размер архива: $BACKUP_SIZE" # Удаляем отдельный файл дампа, так как он теперь в архиве rm -f "$DB_DUMP_PATH" log "Отдельный файл дампа БД удален (включен в архив)" else log "ОШИБКА: Не удалось создать архив" # Пытаемся запустить контейнеры даже при ошибке log "Запускаем контейнеры после ошибки..." docker-compose -f "$COMPOSE_FILE" up -d exit 1 fi # Запускаем контейнеры обратно log "Запускаем контейнеры Evolution API..." docker-compose -f "$COMPOSE_FILE" up -d if [ $? -eq 0 ]; then log "Контейнеры успешно запущены" else log "ОШИБКА: Не удалось запустить контейнеры" exit 1 fi # Ждем запуска сервисов sleep 15 # Проверяем что все контейнеры работают log "Проверяем статус контейнеров..." RUNNING_CONTAINERS=$(docker-compose -f "$COMPOSE_FILE" ps --services --filter "status=running" | wc -l) TOTAL_CONTAINERS=$(docker-compose -f "$COMPOSE_FILE" ps --services | wc -l) if [ "$RUNNING_CONTAINERS" -eq "$TOTAL_CONTAINERS" ]; then log "Все контейнеры ($RUNNING_CONTAINERS/$TOTAL_CONTAINERS) работают корректно" else log "ПРЕДУПРЕЖДЕНИЕ: Работают только $RUNNING_CONTAINERS из $TOTAL_CONTAINERS контейнеров" fi # Проверяем доступность базы данных log "Проверяем подключение к базе данных..." export PGPASSWORD="$DB_PASSWORD" if docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" -d "$DB_NAME" > /dev/null 2>&1; then log "База данных доступна и готова к работе" else log "ПРЕДУПРЕЖДЕНИЕ: База данных может быть недоступна" fi unset PGPASSWORD # Удаляем старые бекапы log "Удаляем бекапы старше $RETENTION_DAYS дней..." DELETED_COUNT=$(find "$BACKUP_DIR" -name "evolution_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete -print | wc -l) log "Удалено старых бекапов: $DELETED_COUNT" # Показываем статистику бекапов BACKUP_COUNT=$(ls -1 "${BACKUP_DIR}"/evolution_backup_*.tar.gz 2>/dev/null | wc -l) TOTAL_SIZE=$(du -sh "${BACKUP_DIR}" 2>/dev/null | cut -f1) log "Общее количество бекапов: $BACKUP_COUNT" log "Общий размер папки бекапов: $TOTAL_SIZE" # Получаем информацию о свободном месте на диске BACKUP_DISK_USAGE=$(df -h "$BACKUP_DIR" | awk 'NR==2 {print $4 " свободно из " $2 " (" $5 " занято)"}') ROOT_DISK_USAGE=$(df -h / | awk 'NR==2 {print $4 " свободно из " $2 " (" $5 " занято)"}') log "Свободное место на диске бекапов: $BACKUP_DISK_USAGE" if [ "$BACKUP_DIR" != "/" ] && [ "$(df "$BACKUP_DIR" | awk 'NR==2 {print $1}')" != "$(df / | awk 'NR==2 {print $1}')" ]; then log "Свободное место на корневом диске: $ROOT_DISK_USAGE" fi # Получаем процент заполнения диска с бекапами для предупреждений BACKUP_DISK_PERCENT=$(df "$BACKUP_DIR" | awk 'NR==2 {print $5}' | sed 's/%//') if [ "$BACKUP_DISK_PERCENT" -gt 90 ]; then log "⚠️ ПРЕДУПРЕЖДЕНИЕ: Диск заполнен более чем на 90%!" elif [ "$BACKUP_DISK_PERCENT" -gt 80 ]; then log "⚠️ ВНИМАНИЕ: Диск заполнен более чем на 80%" fi log "=== Резервное копирование завершено успешно ===" # Формируем сообщение для Telegram TELEGRAM_MESSAGE="✅ Evolution API backup completed 📁 Backup: $BACKUP_NAME ($BACKUP_SIZE) 💾 DB dump: $DB_DUMP_SIZE 📊 Total backups: $BACKUP_COUNT 💿 Disk space: $BACKUP_DISK_USAGE" # Добавляем предупреждение о месте, если нужно if [ "$BACKUP_DISK_PERCENT" -gt 90 ]; then TELEGRAM_MESSAGE="$TELEGRAM_MESSAGE ⚠️ WARNING: Disk >90% full!" elif [ "$BACKUP_DISK_PERCENT" -gt 80 ]; then TELEGRAM_MESSAGE="$TELEGRAM_MESSAGE ⚠️ ATTENTION: Disk >80% full" fi # Отправляем уведомление в Telegram (опционально) curl -s -X POST "https://api.telegram.org/botВАШ_ТОКЕН_БОТА/sendMessage" \ -d chat_id="ВАШ_CHAT_ID" \ -d text="$TELEGRAM_MESSAGE" > /dev/null exit 0
3. Настройка переменных
После создания скрипта обязательно отредактируйте следующие переменные:
# Основные настройки (проверьте пути под вашу систему) COMPOSE_FILE="/opt/evolution-api/docker-compose.yml" # Путь к docker-compose.yml EVOLUTION_DIR="/opt/evolution-api" # Директория Evolution API BACKUP_DIR="/opt/backups/evolution-api" # Директория для бекапов RETENTION_DAYS=10 # Срок хранения бекапов # ⚠️ ОБЯЗАТЕЛЬНО ИЗМЕНИТЕ эти параметры безопасности: DB_PASSWORD="ВАШ_ПАРОЛЬ_БД" # Пароль от PostgreSQL (из docker-compose.yml) curl ... "botВАШ_ТОКЕН_БОТА" ... # Токен Telegram бота chat_id="ВАШ_CHAT_ID" # Ваш Telegram chat_id
<note warning> Безопасность: Обязательно замените все плейсхолдеры на реальные значения! Пароль должен совпадать с `POSTGRES_PASSWORD` из вашего `docker-compose.yml`. </note>
4. Настройка Telegram уведомлений (опционально)
Для получения уведомлений о результатах резервного копирования:
- Создайте Telegram бота через [@BotFather](https://t.me/botfather)
- Получите токен бота
- Узнайте ваш chat_id (можно использовать [@userinfobot](https://t.me/userinfobot))
- Замените токен и chat_id в конце скрипта
# Замените эти значения на свои curl -s -X POST "https://api.telegram.org/bot[ВАШ_ТОКЕН]/sendMessage" \ -d chat_id="[ВАШ_CHAT_ID]" \ -d text="✅ Evolution API backup completed: $BACKUP_NAME ($BACKUP_SIZE)"
Использование скрипта
Ручной запуск
# Запуск с выводом в консоль /opt/scripts/evolution-backup.sh # Запуск в фоновом режиме nohup /opt/scripts/evolution-backup.sh > /dev/null 2>&1 &
Автоматический запуск через Cron
# Редактируем crontab crontab -e # Добавляем задание (например, каждый день в 3:00 ночи) 0 3 * * * /opt/scripts/evolution-backup.sh >/dev/null 2>&1 # Или с логированием cron ошибок 0 3 * * * /opt/scripts/evolution-backup.sh 2>> /var/log/evolution-backup-cron.log
Примеры расписаний Cron:
- `0 3 * * *` - каждый день в 3:00
- `0 2 * * 0` - каждое воскресенье в 2:00
- `0 1 1 * *` - 1 числа каждого месяца в 1:00
- `0 */6 * * *` - каждые 6 часов
Процесс резервного копирования
Скрипт выполняет следующие операции:
- Проверка окружения - проверяет наличие файлов и запущенные контейнеры
- Создание SQL дампа - создает дамп базы данных PostgreSQL
- Остановка контейнеров - корректно останавливает все сервисы
- Создание архива - упаковывает все данные в tar.gz
- Запуск контейнеров - восстанавливает работу системы
- Проверка состояния - проверяет что все сервисы запустились
- Очистка старых бекапов - удаляет файлы старше указанного срока
- Отправка уведомлений - отправляет статус в Telegram
<note> Время простоя: Обычно система недоступна 30-60 секунд во время создания бекапа. </note>
Мониторинг дискового пространства
Скрипт автоматически отслеживает состояние дискового пространства:
| Уровень заполнения | Действие | Сообщение |
|---|---|---|
| < 80% | Нормальная работа | Информация в логе |
| 80-90% | Предупреждение | «⚠️ ВНИМАНИЕ: Диск заполнен более чем на 80%» |
| > 90% | Критическое предупреждение | «⚠️ ПРЕДУПРЕЖДЕНИЕ: Диск заполнен более чем на 90%!» |
# Проверка свободного места вручную df -h /opt/backups/evolution-api # Расчет размера всех бекапов du -sh /opt/backups/evolution-api/* # Принудительная очистка старых бекапов (осторожно!) find /opt/backups/evolution-api -name "evolution_backup_*.tar.gz" -mtime +7 -delete
Рекомендации по управлению дисковым пространством:
- При заполнении > 80% - рассмотрите уменьшение срока хранения бекапов
- При заполнении > 90% - немедленно очистите старые бекапы или увеличьте дисковое пространство
- Настройте отдельный диск для бекапов, если это критично
Мониторинг и логи
Просмотр логов
# Последние 50 строк лога tail -50 /opt/backups/evolution-api/backup.log # Мониторинг в реальном времени tail -f /opt/backups/evolution-api/backup.log # Логи за сегодня grep "$(date '+%Y-%m-%d')" /opt/backups/evolution-api/backup.log
Проверка статуса бекапов
# Список всех бекапов ls -lah /opt/backups/evolution-api/evolution_backup_*.tar.gz # Размер директории бекапов du -sh /opt/backups/evolution-api/ # Последний успешный бекап grep "завершено успешно" /opt/backups/evolution-api/backup.log | tail -1
Настройка ротации логов
# Создаем конфиг для logrotate cat > /etc/logrotate.d/evolution-backup << EOF /opt/backups/evolution-api/backup.log { weekly rotate 8 compress delaycompress notifempty create 644 root root } EOF
Восстановление из резервной копии
Полное восстановление системы
<note warning> Внимание! Процедура восстановления полностью заменит текущие данные. Убедитесь что система остановлена. </note>
# 1. Останавливаем Evolution API cd /opt/evolution-api docker-compose down # 2. Создаем резервную копию текущих данных (на всякий случай) mv store store_backup_$(date +%Y%m%d) mv instances instances_backup_$(date +%Y%m%d) mv postgres_data postgres_data_backup_$(date +%Y%m%d) mv redis_data redis_data_backup_$(date +%Y%m%d) # 3. Распаковываем бекап cd /opt/evolution-api tar -xzf /opt/backups/evolution-api/evolution_backup_YYYYMMDD_HHMMSS.tar.gz # 4. Запускаем контейнеры docker-compose up -d # 5. Ждем запуска и проверяем sleep 15 docker-compose ps
Восстановление только базы данных
# 1. Распаковываем дамп из архива cd /tmp tar -xzf /opt/backups/evolution-api/evolution_backup_YYYYMMDD_HHMMSS.tar.gz evolution_backup_YYYYMMDD_HHMMSS_database.sql # 2. Восстанавливаем базу данных cd /opt/evolution-api export PGPASSWORD="Fd6ffgdkF98hGf69" docker exec -i evolution_postgres psql -U evolution_user -d evolution_db < /tmp/evolution_backup_YYYYMMDD_HHMMSS_database.sql # 3. Перезапускаем API для применения изменений docker-compose restart evolution-api
Решение проблем
Частые ошибки и решения
Ошибка: «Контейнеры не запущены!»
# Решение: Запустите контейнеры перед созданием бекапа cd /opt/evolution-api docker-compose up -d
Ошибка: «Не удалось создать дамп базы данных»
# Проверяем статус PostgreSQL docker exec evolution_postgres pg_isready -U evolution_user # Проверяем логи PostgreSQL docker logs evolution_postgres # Проверяем подключение docker exec evolution_postgres psql -U evolution_user -d evolution_db -c "SELECT version();"
Ошибка: «Permission denied» при доступе к файлам
# Проверяем и исправляем права sudo chown -R $(whoami):$(whoami) /opt/evolution-api/ sudo chmod -R 755 /opt/evolution-api/
Контейнеры не запускаются после бекапа
# Проверяем логи Docker docker-compose logs # Принудительно пересоздаем контейнеры docker-compose down docker-compose up -d --force-recreate
Проверка целостности бекапов
# Тест архива на целостность tar -tzf /opt/backups/evolution-api/evolution_backup_YYYYMMDD_HHMMSS.tar.gz > /dev/null && echo "OK" || echo "CORRUPTED" # Проверка размера бекапа (должен быть больше 1MB) if [ $(stat -f%z /opt/backups/evolution-api/evolution_backup_YYYYMMDD_HHMMSS.tar.gz) -gt 1048576 ]; then echo "Размер бекапа нормальный" else echo "Подозрительно маленький размер бекапа" fi
Тестирование восстановления
Рекомендуется периодически тестировать процедуру восстановления:
# Создаем тестовую среду mkdir -p /tmp/evolution-test cd /tmp/evolution-test # Распаковываем последний бекап tar -xzf /opt/backups/evolution-api/evolution_backup_$(ls -t /opt/backups/evolution-api/evolution_backup_*.tar.gz | head -1 | cut -d'/' -f5) # Проверяем содержимое ls -la echo "Тест восстановления завершен. Проверьте содержимое папки /tmp/evolution-test"
Рекомендации по безопасности
- Шифрование бекапов: Рассмотрите использование GPG для шифрования архивов
- Удаленное хранение: Копируйте бекапы на удаленный сервер или облачное хранилище
- Мониторинг доступа: Следите за доступом к директории с бекапами
- Регулярное тестирование: Тестируйте восстановление минимум раз в месяц
- Документирование изменений: Ведите журнал всех изменений в системе
Контакты и поддержка
При возникновении проблем с резервным копированием:
- Проверьте логи: `/opt/backups/evolution-api/backup.log`
- Проверьте системные ресурсы: `df -h` и `free -h`
- Обратитесь к системному администратору
- Создайте issue в системе отслеживания задач
— Документ создан: current_date | Версия: 1.0 | Автор: System Admin