====== Автоматическое резервное копирование n8n ====== ===== Описание ===== Система автоматического резервного копирования для n8n, которая создает полные бекапы всех данных, включая воркфлоу, настройки, пользовательские ноды и конфигурацию. **ВАЖНО**: Скрипт автоматически включает ВСЁ содержимое папок данных n8n - любые новые файлы попадут в бекап автоматически. ===== Что включается в бекап ===== ^ Компонент ^ Описание ^ Расположение ^ | Данные n8n | Воркфлоу, настройки, база SQLite | `/opt/n8n/n8n_data/` | | Пользовательские ноды | Кастомные расширения | `/opt/n8n/n8n_nodes/` | | Docker конфигурация | docker-compose.yml | `/opt/n8n/docker-compose.yml` | ===== Структура проекта ===== /opt/ ├── n8n/ │ ├── docker-compose.yml # Конфигурация контейнера │ ├── n8n_data/ # Основные данные n8n │ └── n8n_nodes/ # Пользовательские ноды ├── backups/ │ └── n8n/ # Папка для бекапов └── scripts/ └── n8n-backup.sh # Скрипт резервного копирования ===== Установка и настройка ===== ==== Шаг 1: Создание структуры папок ==== # Создание необходимых папок sudo mkdir -p /opt/scripts sudo mkdir -p /opt/backups/n8n sudo chown -R $USER:$USER /opt/backups sudo chown -R $USER:$USER /opt/scripts ==== Шаг 2: Создание скрипта ==== Создайте файл `/opt/scripts/n8n-backup.sh`: sudo nano /opt/scripts/n8n-backup.sh Вставьте следующий код: #!/bin/bash # Скрипт резервного копирования n8n # Запуск: /opt/scripts/n8n-backup.sh # Настройки COMPOSE_FILE="/opt/n8n/docker-compose.yml" N8N_DIR="/opt/n8n" BACKUP_DIR="/opt/backups/n8n" DATE=$(date +"%Y%m%d_%H%M%S") BACKUP_NAME="n8n_backup_${DATE}" RETENTION_DAYS=10 # Храним бекапы 10 дней # Настройки контейнера N8N_CONTAINER="n8n" # Логирование 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 "=== Начало резервного копирования n8n ===" # Проверяем что compose файл существует if [ ! -f "$COMPOSE_FILE" ]; then log "ОШИБКА: Файл $COMPOSE_FILE не найден!" exit 1 fi # Переходим в директорию с n8n cd "$N8N_DIR" || { log "ОШИБКА: Не удалось перейти в директорию $N8N_DIR" exit 1 } # Проверяем что контейнер запущен log "Проверяем статус контейнера..." if ! docker-compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then log "ОШИБКА: Контейнер не запущен! Запустите его перед созданием бекапа." exit 1 fi # Показываем что будет включено в бекап log "Анализируем содержимое папок данных n8n..." N8N_DATA_CONTENTS=$(ls -la /opt/n8n/n8n_data/ 2>/dev/null | grep -v "^total" | grep -v "^\." | awk '{print $9}' | grep -v "^$" | tr '\n' ' ') N8N_NODES_CONTENTS=$(ls -la /opt/n8n/n8n_nodes/ 2>/dev/null | grep -v "^total" | grep -v "^\." | awk '{print $9}' | grep -v "^$" | tr '\n' ' ') log "n8n_data содержит: $N8N_DATA_CONTENTS" log "n8n_nodes содержит: $N8N_NODES_CONTENTS" # Получаем размер папок до бекапа N8N_DATA_SIZE=$(du -sh /opt/n8n/n8n_data/ 2>/dev/null | cut -f1) N8N_NODES_SIZE=$(du -sh /opt/n8n/n8n_nodes/ 2>/dev/null | cut -f1) log "Размер n8n_data: $N8N_DATA_SIZE" log "Размер n8n_nodes: $N8N_NODES_SIZE" # Проверяем количество воркфлоу в n8n log "Проверяем статус n8n перед остановкой..." if docker exec "$N8N_CONTAINER" n8n list:workflow > /dev/null 2>&1; then WORKFLOWS_COUNT=$(docker exec "$N8N_CONTAINER" n8n list:workflow 2>/dev/null | grep -c "^[0-9]" || echo "0") log "Найдено воркфлоу в n8n: $WORKFLOWS_COUNT" else log "ПРЕДУПРЕЖДЕНИЕ: Не удалось получить количество воркфлоу" WORKFLOWS_COUNT="неизвестно" fi # Останавливаем контейнер log "Останавливаем контейнер n8n..." docker-compose -f "$COMPOSE_FILE" down if [ $? -eq 0 ]; then log "Контейнер успешно остановлен" else log "ОШИБКА: Не удалось остановить контейнер" exit 1 fi # Ждем пару секунд для полной остановки sleep 5 # Создаем архив с данными - автоматически включает все содержимое папок log "Создаем архив данных n8n..." BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" # Создаем архив с данными n8n и конфигурацией tar -czf "$BACKUP_PATH" \ --exclude='*.log' \ --exclude='**/lost+found' \ --exclude='**/.tmp' \ --exclude='**/tmp/*' \ --exclude='**/.cache' \ -C "/opt/n8n" \ n8n_data/ \ n8n_nodes/ \ docker-compose.yml if [ $? -eq 0 ]; then log "Архив создан: $BACKUP_PATH" # Получаем размер архива BACKUP_SIZE=$(du -h "$BACKUP_PATH" | cut -f1) log "Размер архива: $BACKUP_SIZE" # Показываем что попало в архив log "Содержимое архива (основные папки и файлы):" tar -tzf "$BACKUP_PATH" | head -20 | while read file; do log " $file" done TOTAL_FILES=$(tar -tzf "$BACKUP_PATH" | wc -l) log "Общее количество файлов в архиве: $TOTAL_FILES" else log "ОШИБКА: Не удалось создать архив" # Пытаемся запустить контейнер даже при ошибке log "Запускаем контейнер после ошибки..." docker-compose -f "$COMPOSE_FILE" up -d exit 1 fi # Запускаем контейнер обратно log "Запускаем контейнер n8n..." docker-compose -f "$COMPOSE_FILE" up -d if [ $? -eq 0 ]; then log "Контейнер успешно запущен" else log "ОШИБКА: Не удалось запустить контейнер" exit 1 fi # Ждем запуска сервиса sleep 15 # Проверяем что контейнер работает log "Проверяем статус контейнера..." if docker ps | grep -q "$N8N_CONTAINER.*Up"; then log "Контейнер n8n работает корректно" else log "ПРЕДУПРЕЖДЕНИЕ: Контейнер n8n может работать некорректно" fi # Проверяем доступность n8n API log "Проверяем доступность n8n..." sleep 10 # Дополнительное время для полного запуска n8n if docker exec "$N8N_CONTAINER" n8n --version > /dev/null 2>&1; then N8N_VERSION=$(docker exec "$N8N_CONTAINER" n8n --version 2>/dev/null || echo "неизвестно") log "n8n работает корректно, версия: $N8N_VERSION" else log "ПРЕДУПРЕЖДЕНИЕ: n8n может работать некорректно" N8N_VERSION="неизвестно" fi # Проверяем что воркфлоу доступны после перезапуска log "Проверяем воркфлоу после перезапуска..." sleep 5 if docker exec "$N8N_CONTAINER" n8n list:workflow > /dev/null 2>&1; then WORKFLOWS_COUNT_AFTER=$(docker exec "$N8N_CONTAINER" n8n list:workflow 2>/dev/null | grep -c "^[0-9]" || echo "0") log "Воркфлоу после перезапуска: $WORKFLOWS_COUNT_AFTER" if [ "$WORKFLOWS_COUNT" != "неизвестно" ] && [ "$WORKFLOWS_COUNT" = "$WORKFLOWS_COUNT_AFTER" ]; then log "Количество воркфлоу совпадает - восстановление прошло успешно" elif [ "$WORKFLOWS_COUNT" != "$WORKFLOWS_COUNT_AFTER" ]; then log "ПРЕДУПРЕЖДЕНИЕ: Количество воркфлоу изменилось ($WORKFLOWS_COUNT -> $WORKFLOWS_COUNT_AFTER)" fi else log "ПРЕДУПРЕЖДЕНИЕ: Не удалось проверить воркфлоу после перезапуска" WORKFLOWS_COUNT_AFTER="ошибка" fi # Удаляем старые бекапы log "Удаляем бекапы старше $RETENTION_DAYS дней..." DELETED_COUNT=$(find "$BACKUP_DIR" -name "n8n_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete -print | wc -l) log "Удалено старых бекапов: $DELETED_COUNT" # Показываем статистику бекапов BACKUP_COUNT=$(ls -1 "${BACKUP_DIR}"/n8n_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="✅ n8n backup completed 📁 Backup: $BACKUP_NAME ($BACKUP_SIZE) 💾 n8n_data: $N8N_DATA_SIZE 🔧 n8n_nodes: $N8N_NODES_SIZE 📊 Total backups: $BACKUP_COUNT 📄 Files in archive: $TOTAL_FILES 🔄 Workflows: $WORKFLOWS_COUNT_AFTER 📋 n8n version: $N8N_VERSION 💿 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 (опционально) # Замените на свой BOT_TOKEN и CHAT_ID curl -s -X POST "https://api.telegram.org/bot[YOUR_BOT_TOKEN]/sendMessage" \ -d chat_id="[YOUR_CHAT_ID]" \ -d text="$TELEGRAM_MESSAGE" > /dev/null exit 0 ==== Шаг 3: Настройка прав доступа ==== # Делаем скрипт исполняемым sudo chmod +x /opt/scripts/n8n-backup.sh # Проверяем права ls -la /opt/scripts/n8n-backup.sh ==== Шаг 4: Тестовый запуск ==== # Запуск тестового бекапа sudo /opt/scripts/n8n-backup.sh # Проверка результата ls -la /opt/backups/n8n/ cat /opt/backups/n8n/backup.log ===== Автоматизация через Cron ===== ==== Настройка ежедневного бекапа ==== # Открываем crontab sudo crontab -e # Добавляем задачу (бекап каждый день в 3:00 ночи) 0 3 * * * /opt/scripts/n8n-backup.sh >> /var/log/n8n-backup-cron.log 2>&1 ==== Альтернативные расписания ==== # Каждые 6 часов 0 */6 * * * /opt/scripts/n8n-backup.sh # Каждый день в 2:30 30 2 * * * /opt/scripts/n8n-backup.sh # Два раза в день (утром и вечером) 0 9,21 * * * /opt/scripts/n8n-backup.sh ==== Проверка работы Cron ==== # Проверить статус cron sudo systemctl status cron # Посмотреть активные задачи sudo crontab -l # Посмотреть логи cron sudo tail -f /var/log/n8n-backup-cron.log ===== Мониторинг ===== ==== Настройка Telegram уведомлений ==== 1. **Создайте бота**: Отправьте `/start` боту @BotFather в Telegram 2. **Получите токен**: Сохраните Bot Token 3. **Узнайте Chat ID**: Отправьте сообщение боту, затем откройте: `https://api.telegram.org/bot[YOUR_BOT_TOKEN]/getUpdates` 4. **Обновите скрипт**: Замените `[YOUR_BOT_TOKEN]` и `[YOUR_CHAT_ID]` на свои значения ==== Мониторинг места на диске ==== # Проверка места в папке бекапов df -h /opt/backups/n8n/ # Размер всех бекапов du -sh /opt/backups/n8n/ # Список всех бекапов с размерами ls -lah /opt/backups/n8n/n8n_backup_*.tar.gz ===== Восстановление из бекапа ===== ==== Полное восстановление ==== # Остановите n8n cd /opt/n8n docker-compose down # Найдите нужный бекап ls -la /opt/backups/n8n/ # Создайте резервную копию текущих данных sudo mv /opt/n8n/n8n_data /opt/n8n/n8n_data_backup sudo mv /opt/n8n/n8n_nodes /opt/n8n/n8n_nodes_backup # Извлеките архив (замените на ваш файл) cd /tmp tar -xzf /opt/backups/n8n/n8n_backup_YYYYMMDD_HHMMSS.tar.gz # Восстановите данные sudo cp -r n8n_data /opt/n8n/ sudo cp -r n8n_nodes /opt/n8n/ # Восстановите конфигурацию (если нужно) cp docker-compose.yml /opt/n8n/ # Запустите n8n cd /opt/n8n docker-compose up -d ==== Частичное восстановление ==== # Восстановить только воркфлоу (n8n_data) cd /tmp tar -xzf /opt/backups/n8n/n8n_backup_YYYYMMDD_HHMMSS.tar.gz n8n_data/ sudo cp -r n8n_data/* /opt/n8n/n8n_data/ # Восстановить только пользовательские ноды tar -xzf /opt/backups/n8n/n8n_backup_YYYYMMDD_HHMMSS.tar.gz n8n_nodes/ sudo cp -r n8n_nodes/* /opt/n8n/n8n_nodes/ ===== Устранение неполадок ===== ==== Основные проблемы ==== === Ошибка "Container not found" === **Причина**: Неправильное имя контейнера **Решение**: Проверьте имя контейнера: docker ps # Обновите переменную N8N_CONTAINER в скрипте если нужно === Ошибка доступа к воркфлоу === **Причина**: n8n еще не запустился полностью **Решение**: Увеличьте время ожидания в скрипте или проверьте статус: docker logs n8n docker exec n8n n8n list:workflow === Большой размер бекапа === **Причина**: Накопились большие файлы в данных n8n **Решение**: Очистите логи и временные файлы: # Посмотрите что занимает место du -sh /opt/n8n/n8n_data/* # Очистите старые логи n8n если есть sudo find /opt/n8n/n8n_data -name "*.log" -mtime +7 -delete ==== Проверка логов ==== # Основной лог скрипта tail -f /opt/backups/n8n/backup.log # Лог cron tail -f /var/log/n8n-backup-cron.log # Логи контейнера n8n docker logs n8n ===== Дополнительные настройки ===== ==== Изменение времени хранения ==== В скрипте измените: RETENTION_DAYS=10 # Храним бекапы 10 дней ==== Изменение папки бекапов ==== В скрипте измените: BACKUP_DIR="/opt/backups/n8n" ===== Заключение ===== Данный скрипт обеспечивает: - **Полное резервное копирование** всех данных n8n - **Автоматическое включение** новых файлов в папках данных - **Проверку целостности** воркфлоу до и после бекапа - **Безопасное выполнение** с остановкой и запуском контейнера - **Очистку старых бекапов** для экономии места - **Детальное логирование** всех операций - **Telegram уведомления** о статусе бекапа - **Мониторинг места на диске** с предупреждениями **Результат**: Надежная система резервного копирования n8n с автоматическим контролем целостности воркфлоу. ---- //Инструкция протестирована на Ubuntu Server с Docker Compose. Регулярно проверяйте работоспособность бекапов и процедуры восстановления.//