Статья в формате шпаргалки — для тех, кто понимает, о чём тут речь и зачем оно нужно. Я бы был очень рад, если бы такая была у меня вчера. Здесь максимально кратко изложен мой опыт, без воды и лишних отступлений. В итоге пополучим полностью готовую инфраструктуру под свои проекты на n8n.
Конечно, статей «как развернуть n8n на своём сервере» полно. Если эта кажется такой же — значит, либо вы не целевой читатель, либо я чего‑то не понимаю.
Пункт 0
Берем в аренду простенький сервак (я тестил на 2cpu, 2gb ram. Уверен, что и на 1cpu нормально будет). Привязываем к нему домен в dns, я использую поддомен третьего уровня на своем личном домене для pet проектов.
Для бекапов берём S3-совместимое хранилище. Стоить будет примерно 0 рублей, если не хранить гигабайты (а мы не будем).
В итоге: сервак ≈ двойная шавы в месяц, домен ≈ один капучино в год.А на выходе — полная свобода для своих проектов, автоматизаций, ботов и всего, что можно накрутить на n8n.
n8n
Ставим Docker и Docker Compose:
sudo apt update sudo apt install -y ca-certificates curl gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Создаём ./n8n и кладём туда конфиг docker-compose.yml:
version: '3.8' services: n8n: image: n8nio/n8n:latest ports: - "5678:5678" environment: - N8N_PORT=5678 - N8N_PROTOCOL=http - N8N_HOST={ваш_домен} - WEBHOOK_URL=https://{ваш_домен} volumes: - ./data:/home/node/.n8n restart: always
Замените {ваш_домен} на свой (например n8n.example.com).
Перед запуском создаём папку под хранилище n8n и выдаём правильные права:
mkdir -p ~/n8n/data sudo chown -R 1000:1000 ~/n8n/data
Запуск:
docker compose up -d docker ps
nginx
Создаём конфиг под наш домен:
sudo nano /etc/nginx/sites-available/{ваш_домен}
Вставляем:
server { listen 80; server_name {ваш_домен}; location / { proxy_pass http://localhost:5678; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # --- ВАЖНО: WebSocket --- proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_http_version 1.1; } }
WebSocket нужен, чтобы интерфейс n8n в браузере мог работать с сервером.
Активируем конфиг:
sudo ln -s /etc/nginx/sites-available/{ваш_домен} /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
Ставим SSL:
sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d {ваш_домен}
💫 Всё - n8n работает на вашем домене.
postgres
Можно, конечно, использовать встроенную бдшку в n8n, но яйца в одну корзину не кладём.Да и хочется всё по красоте: отдельная бд, бекапы, проекты — как у больших дядь.
Готовим структуру:
mkdir -p ~/postgres cd ~/postgres mkdir data
Создаём docker-compose.yml:
version: "3.8" services: postgres: image: postgres:16 restart: always environment: POSTGRES_USER: admin POSTGRES_PASSWORD: {ваш_пароль} ports: - "5432:5432" volumes: - ./data:/var/lib/postgresql/data
Запускаем:
docker compose up -d docker ps
Небольшое наставление: на каждый проект — отдельная база и отдельный пользователь с правами только на свою базу.
Подключаемся:
docker exec -it postgres-postgres-1 psql -U admin
Создаём базу:
CREATE DATABASE project1;
Создаём пользователя:
CREATE USER project1_user WITH PASSWORD '{ваш_пароль}'; GRANT ALL PRIVILEGES ON DATABASE project1 TO project1_user; GRANT ALL ON SCHEMA public TO project1_user;
Бекапы
Бекапим и базу, и данные n8n — чтобы и воркфлоу наши бекапились и мы ничего не потеряли точно.
Будем работать через MinIO Client (mc).
Ставим:
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc chmod +x /usr/local/bin/mc
Создаём подключение:
mc alias set beget https://{URL\\_S3} {ACCESS_KEY} {SECRET_KEY} --api S3v4
Пример:
mc alias set beget https://s3.ru1.storage.beget.cloud KXXX SXXX --api S3v4
Проверяем:
mc ls beget/
Создаём ~/backup.sh:
DATE=$(date +"%Y-%m-%d_%H-%M") BUCKET="{имя бакета}" TELEGRAM_BOT_TOKEN="ТОКЕН" TELEGRAM_CHAT_ID="ID" send_telegram() { MESSAGE="$1" curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \ -d chat_id="$TELEGRAM_CHAT_ID" \ -d text="$MESSAGE" \ -d parse_mode="Markdown" \ -d disable_notification=true } # --- Backup PostgreSQL --- echo "Dumping PostgreSQL..." docker exec postgres-postgres-1 pg_dumpall -U admin | gzip > /tmp/pg_backup_$DATE.sql.gz if [ -f "/tmp/pg_backup_$DATE.sql.gz" ]; then mc cp /tmp/pg_backup_$DATE.sql.gz beget/$BUCKET/postgres/ rm /tmp/pg_backup_$DATE.sql.gz PG_STATUS="PostgreSQL backup: OK" else PG_STATUS="PostgreSQL backup: FAILED" fi # --- Backup n8n --- echo "Backing up n8n..." tar -czf /tmp/n8n_backup_$DATE.tar.gz ~/n8n/data if [ -f "/tmp/n8n_backup_$DATE.tar.gz" ]; then mc cp /tmp/n8n_backup_$DATE.tar.gz beget/$BUCKET/n8n/ rm /tmp/n8n_backup_$DATE.tar.gz N8N_STATUS="n8n backup: OK" else N8N_STATUS="n8n backup: FAILED" fi # --- Clean old backups (older than 14 days) --- for file in $(mc ls beget/$BUCKET/postgres/ | awk '$1 < strftime("%Y-%m-%d", systime() - 1209600) {print $5}'); do mc rm beget/$BUCKET/postgres/$file done for file in $(mc ls beget/$BUCKET/n8n/ | awk '$1 < strftime("%Y-%m-%d", systime() - 1209600) {print $5}'); do mc rm beget/$BUCKET/n8n/$file done # --- SEND TELEGRAM NOTIFICATION --- MESSAGE="Бэкап завершён $PG_STATUS $N8N_STATUS" send_telegram "$MESSAGE" echo "Backup completed!"
Делаем исполняемым:
chmod +x ~/backup.sh ./backup.sh
Если в телеге пришло - всё ок.
cron для бекапов
Настраиваем запуск каждые 6 часов:
crontab -e
Добавляем:
0 */6 * * * /bin/bash /root/backup.sh >> /root/backup.log 2>&1
Готово. Теперь у вас:
n8n
отдельная PostgreSQL
домен
SSL
автоматические бекапы в S3
уведомления в Telegram
