vm:chatwoot:03-backup

Это старая версия документа!


Резервное копирование Chatwoot

Автоматическое резервное копирование системы Chatwoot включает в себя создание SQL дампа базы данных PostgreSQL и архивирование всех важных файлов системы.

  • База данных - SQL дамп базы chatwoot_production через pg_dump
  • Файлы хранилища - директория storage/ с загруженными файлами и изображениями
  • Данные PostgreSQL - директория postgres_data/ с бинарными данными БД
  • Данные Redis - директория redis_data/ с кэшем и очередями задач
  • Конфигурация - файлы docker-compose.yml и .env

⚠️ Важно: Директория postgres_data/ включается для полного резервирования, но при необходимости её можно исключить из архива, так как SQL дамп базы данных уже содержит все необходимые данные для восстановления. Бинарное копирование postgres_data/ требуется только при необходимости точного клонирования PostgreSQL с сохранением всех системных настроек.

mkdir -p /opt/scripts
mkdir -p /opt/backups/chatwoot

Создайте файл /opt/scripts/chatwoot-backup.sh:

nano /opt/scripts/chatwoot-backup.sh

Вставьте следующий код:

#!/bin/bash
 
# Скрипт резервного копирования Chatwoot
# Запуск: /opt/scripts/chatwoot-backup.sh
 
# Настройки
COMPOSE_FILE="/opt/chatwoot/docker-compose.yml"
CHATWOOT_DIR="/opt/chatwoot"
BACKUP_DIR="/opt/backups/chatwoot"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_NAME="chatwoot_backup_${DATE}"
RETENTION_DAYS=30  # Храним бекапы 30 дней
 
# Настройки базы данных
DB_NAME="chatwoot_production"
DB_USER="postgres"
DB_PASSWORD="YOUR_DB_PASSWORD"  # Замените на ваш пароль от БД
DB_CONTAINER="chatwoot_postgres_1"
 
# Логирование
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 "=== Начало резервного копирования Chatwoot ==="
 
# Проверяем что compose файл существует
if [ ! -f "$COMPOSE_FILE" ]; then
    log "ОШИБКА: Файл $COMPOSE_FILE не найден!"
    exit 1
fi
 
# Переходим в директорию с Chatwoot
cd "$CHATWOOT_DIR" || {
    log "ОШИБКА: Не удалось перейти в директорию $CHATWOOT_DIR"
    exit 1
}
 
# Проверяем что контейнеры запущены
if ! docker-compose ps | grep -q "Up"; then
    log "ПРЕДУПРЕЖДЕНИЕ: Не все контейнеры запущены"
fi
 
# Создаем дамп базы данных
log "Создаем дамп базы данных..."
DB_DUMP_FILE="${BACKUP_DIR}/${BACKUP_NAME}_database.sql"
 
docker exec -t "$DB_CONTAINER" pg_dump -U "$DB_USER" -d "$DB_NAME" > "$DB_DUMP_FILE"
 
if [ $? -eq 0 ]; then
    log "Дамп базы данных создан: $DB_DUMP_FILE"
    DB_SIZE=$(du -h "$DB_DUMP_FILE" | cut -f1)
    log "Размер дампа базы данных: $DB_SIZE"
else
    log "ОШИБКА: Не удалось создать дамп базы данных"
    exit 1
fi
 
# Останавливаем контейнеры для консистентного бекапа файлов
log "Останавливаем контейнеры Chatwoot..."
docker-compose -f "$COMPOSE_FILE" down
 
if [ $? -eq 0 ]; then
    log "Контейнеры успешно остановлены"
else
    log "ОШИБКА: Не удалось остановить контейнеры"
    exit 1
fi
 
# Ждем пару секунд для полной остановки
sleep 5
 
# Создаем архив с данными
log "Создаем архив данных..."
BACKUP_ARCHIVE="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
 
tar -czf "$BACKUP_ARCHIVE" \
    --exclude='*.log' \
    --exclude='**/lost+found' \
    --exclude='tmp/' \
    --exclude='log/' \
    storage/ \
    postgres_data/ \
    redis_data/ \
    docker-compose.yml \
    .env
 
if [ $? -eq 0 ]; then
    log "Архив создан: $BACKUP_ARCHIVE"
 
    # Получаем размер архива
    ARCHIVE_SIZE=$(du -h "$BACKUP_ARCHIVE" | cut -f1)
    log "Размер архива: $ARCHIVE_SIZE"
else
    log "ОШИБКА: Не удалось создать архив"
 
    # Пытаемся запустить контейнеры даже при ошибке
    log "Запускаем контейнеры после ошибки..."
    docker-compose -f "$COMPOSE_FILE" up -d
    exit 1
fi
 
# Запускаем контейнеры обратно
log "Запускаем контейнеры Chatwoot..."
docker-compose -f "$COMPOSE_FILE" up -d
 
if [ $? -eq 0 ]; then
    log "Контейнеры успешно запущены"
else
    log "ОШИБКА: Не удалось запустить контейнеры"
    exit 1
fi
 
# Ждем запуска сервисов
log "Ожидаем запуска сервисов..."
sleep 30
 
# Проверяем что все контейнеры работают
log "Проверяем статус контейнеров..."
if docker-compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then
    log "Контейнеры работают корректно"
else
    log "ПРЕДУПРЕЖДЕНИЕ: Некоторые контейнеры могут работать некорректно"
fi
 
# Проверяем подключение к базе данных
log "Проверяем подключение к базе данных..."
if docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" >/dev/null 2>&1; then
    log "База данных доступна"
else
    log "ПРЕДУПРЕЖДЕНИЕ: База данных может быть недоступна"
fi
 
# Создаем итоговый архив с дампом базы данных
log "Создаем итоговый архив с дампом базы данных..."
FINAL_BACKUP="${BACKUP_DIR}/${BACKUP_NAME}_complete.tar.gz"
 
tar -czf "$FINAL_BACKUP" -C "$BACKUP_DIR" "${BACKUP_NAME}.tar.gz" "${BACKUP_NAME}_database.sql"
 
if [ $? -eq 0 ]; then
    log "Итоговый архив создан: $FINAL_BACKUP"
 
    # Получаем размер итогового архива
    FINAL_SIZE=$(du -h "$FINAL_BACKUP" | cut -f1)
    log "Размер итогового архива: $FINAL_SIZE"
 
    # Удаляем промежуточные файлы
    rm -f "$BACKUP_ARCHIVE" "$DB_DUMP_FILE"
    log "Промежуточные файлы удалены"
else
    log "ОШИБКА: Не удалось создать итоговый архив"
fi
 
# Удаляем старые бекапы
log "Удаляем бекапы старше $RETENTION_DAYS дней..."
find "$BACKUP_DIR" -name "chatwoot_backup_*_complete.tar.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "chatwoot_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "chatwoot_backup_*_database.sql" -mtime +$RETENTION_DAYS -delete
 
# Показываем статистику бекапов
BACKUP_COUNT=$(ls -1 "${BACKUP_DIR}"/chatwoot_backup_*_complete.tar.gz 2>/dev/null | wc -l)
log "Общее количество полных бекапов: $BACKUP_COUNT"
 
# Показываем общий размер всех бекапов
TOTAL_SIZE=$(du -sh "$BACKUP_DIR" | cut -f1)
log "Общий размер директории бекапов: $TOTAL_SIZE"
 
log "=== Резервное копирование завершено успешно ==="
 
# Отправляем уведомление (раскомментируйте если нужно)
# curl -s -X POST "https://api.telegram.org/botYOUR_BOT_TOKEN/sendMessage" \
#     -d chat_id="YOUR_CHAT_ID" \
#     -d text="✅ Chatwoot backup completed: $BACKUP_NAME ($FINAL_SIZE)"
 
exit 0
chmod +x /opt/scripts/chatwoot-backup.sh
crontab -e

Добавьте строку для ежедневного запуска в 2:00 ночи:

0 2 * * * /opt/scripts/chatwoot-backup.sh >> /opt/backups/chatwoot/cron.log 2>&1
/opt/scripts/chatwoot-backup.sh
# Проверить созданные файлы
ls -la /opt/backups/chatwoot/
 
# Посмотреть лог
tail -f /opt/backups/chatwoot/backup.log
 
# Проверить размер бекапов
du -sh /opt/backups/chatwoot/

В скрипте найдите и измените строку:

RETENTION_DAYS=30  # Храним бекапы 30 дней

При необходимости измените параметры подключения к БД:

DB_NAME="chatwoot_production"
DB_USER="postgres" 
DB_PASSWORD="YOUR_DB_PASSWORD"  # Замените на ваш пароль от БД
DB_CONTAINER="chatwoot_postgres_1"

Раскомментируйте и настройте в конце скрипта:

curl -s -X POST "https://api.telegram.org/botYOUR_BOT_TOKEN/sendMessage" \
    -d chat_id="YOUR_CHAT_ID" \
    -d text="✅ Chatwoot backup completed: $BACKUP_NAME ($FINAL_SIZE)"

Замените:

  • YOUR_BOT_TOKEN - токен вашего Telegram бота
  • YOUR_CHAT_ID - ваш chat ID в Telegram
cd /opt/backups/chatwoot/
tar -xzf chatwoot_backup_YYYYMMDD_HHMMSS_complete.tar.gz
# Остановить Chatwoot
cd /opt/chatwoot
docker-compose down
 
# Очистить существующую базу данных (осторожно!)
docker-compose up -d postgres
docker exec -it chatwoot_postgres_1 dropdb -U postgres chatwoot_production
docker exec -it chatwoot_postgres_1 createdb -U postgres chatwoot_production
 
# Восстановить из дампа
docker exec -i chatwoot_postgres_1 psql -U postgres -d chatwoot_production < /opt/backups/chatwoot/chatwoot_backup_YYYYMMDD_HHMMSS_database.sql
# Распаковать файлы системы
cd /opt/chatwoot
tar -xzf /opt/backups/chatwoot/chatwoot_backup_YYYYMMDD_HHMMSS.tar.gz
 
# Запустить систему
docker-compose up -d
# Просмотр последних логов
tail -n 50 /opt/backups/chatwoot/backup.log
 
# Статистика бекапов
ls -lh /opt/backups/chatwoot/chatwoot_backup_*_complete.tar.gz
 
# Общий размер
du -sh /opt/backups/chatwoot/
# Удалить бекапы старше 60 дней
find /opt/backups/chatwoot/ -name "chatwoot_backup_*_complete.tar.gz" -mtime +60 -delete

💡 Совет по оптимизации: Если размер бекапов слишком большой, можно исключить директорию postgres_data/ из архива, изменив строку в скрипте:

tar -czf "$BACKUP_ARCHIVE" \
    --exclude='*.log' \
    --exclude='**/lost+found' \
    --exclude='tmp/' \
    --exclude='log/' \
    storage/ \
    # postgres_data/ \  # Закомментировать эту строку
    redis_data/ \
    docker-compose.yml \
    .env

SQL дамп базы данных содержит все необходимые данные для восстановления системы. Бинарная копия postgres_data/ нужна только для точного клонирования PostgreSQL.

  • Убедитесь, что директория /opt/backups/chatwoot/ доступна только root
  • Регулярно проверяйте логи на наличие ошибок
  • Периодически тестируйте процедуру восстановления
  • Рассмотрите возможность хранения бекапов на удаленном сервере
/opt/scripts/chatwoot-backup.sh          # Скрипт резервного копирования
/opt/backups/chatwoot/                   # Директория бекапов
├── backup.log                          # Лог файл
├── cron.log                            # Лог cron задач
└── chatwoot_backup_YYYYMMDD_HHMMSS_complete.tar.gz  # Архивы бекапов
  • vm/chatwoot/03-backup.1756415562.txt.gz
  • Последнее изменение: 2025/08/28 21:12
  • admin