====== Автоматическое резервное копирование 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. Регулярно проверяйте работоспособность бекапов и процедуры восстановления.//