n8n - платформа для автоматизаций с визуальным редактором: из узлов собирают сценарии, которые получают данные из webhook-ов, расписаний и внешних сервисов и передают их дальше. Облачная версия удобна для старта, но объем выполнений и возможности зависят от тарифа сервиса. Установка на собственный VPS переносит эти границы на ваш сервер: вы сами решаете, сколько сценариев запускать, где хранятся данные и ключи.
Ниже разберем, как установить n8n на VPS через Docker Compose с базой PostgreSQL, как вывести сервис наружу по HTTPS через nginx и certbot, как делать резервные копии и обновлять установку.
Что понадобится для установки n8n
- VPS с Linux, доступ по SSH и пользователь с правами sudo;
- Docker и плагин Docker Compose, см. статью Docker на VPS;
- домен, например n8n.example.com, с A-записью на IP сервера, см. статью Домен и DNS;
- nginx и certbot для HTTPS, как описано в статье Сайт на VPS: nginx и SSL.
По ресурсам для комфортной работы подойдет тариф Start: 2 vCPU, 4 ГБ RAM и 35 ГБ диска. Сам n8n, PostgreSQL и несколько сценариев с обработкой данных на таком сервере работают спокойно. На тарифе с 1 ГБ памяти база и n8n начнут конкурировать за память, а сценарии с большими файлами могут падать.
Структура проекта
Создайте каталог проекта и два файла: docker-compose.yml с описанием сервисов и .env с секретами. Файл .env не должен попадать в git и в публичные каталоги.
mkdir -p ~/n8n && cd ~/n8n
nano docker-compose.yml
nano .env
chmod 600 .envФайл docker-compose.yml с PostgreSQL
В конфигурации два сервиса: postgres хранит сценарии, учетные данные и историю выполнений, а n8n работает с ней через внутреннюю сеть Compose. Порт n8n привязан к localhost, поэтому снаружи сервис недоступен напрямую, а доступ дается только через nginx.
services:
postgres:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- n8n_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 10s
timeout: 5s
retries: 5
n8n:
image: n8nio/n8n:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_HOST: n8n.example.com
N8N_PORT: 5678
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
GENERIC_TIMEZONE: Europe/Moscow
TZ: Europe/Moscow
ports:
- "127.0.0.1:5678:5678"
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_pgdata:
n8n_data:Несколько важных переменных. N8N_HOST - только имя хоста без протокола. WEBHOOK_URL - публичный адрес, по которому внешние сервисы будут вызывать ваши webhook-и, он должен совпадать с доменом nginx. N8N_PROTOCOL должен быть https, если сервис работает за HTTPS-прокси. GENERIC_TIMEZONE влияет на расписания cron-узлов.
Тег latest удобен для первого запуска. Для рабочей установки лучше указать конкретную версию n8n, которую вы проверили, например n8nio/n8n:<версия>.
Файл .env с секретами
POSTGRES_PASSWORD=replace-with-long-random-password
N8N_ENCRYPTION_KEY=replace-with-long-random-stringДлинные случайные значения можно сгенерировать командой openssl rand -hex 32. Пароль базы и ключ шифрования должны быть разными.
Запуск контейнеров
cd ~/n8n
docker compose up -d
docker compose ps
docker compose logs -f n8nКогда в логах появится сообщение о запуске редактора, сервис слушает порт 5678 на localhost. Пока nginx не настроен, открыть n8n из браузера нельзя, и это правильно.
Публикация через nginx с HTTPS
nginx принимает запросы на портах 80 и 443, получает сертификат через certbot и передает запросы в n8n. Редактору и части функций нужен WebSocket, поэтому заголовки Upgrade и Connection обязательны. Создайте конфигурацию сайта:
server {
listen 80;
server_name n8n.example.com;
client_max_body_size 16m;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_read_timeout 300s;
}
}sudo nano /etc/nginx/sites-available/n8n
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d n8n.example.comcertbot добавит блок для порта 443 и при необходимости перенаправление с HTTP на HTTPS. Подробности про выпуск сертификата и автообновление описаны в статье Сайт на VPS: nginx и SSL. Порт 5678 наружу открывать не нужно: в фаерволе оставьте только 22, 80 и 443.
Первый вход и учетная запись владельца
Откройте https://n8n.example.com. При первом входе n8n предложит создать учетную запись владельца: укажите email и длинный уникальный пароль. Эта учетная запись получает полный доступ к экземпляру, поэтому делиться ею нельзя. Если версия n8n поддерживает двухфакторную аутентификацию, включите ее в настройках профиля.
Старые версии n8n защищались базовой авторизацией через переменные N8N_BASIC_AUTH_*. В актуальных версиях вход защищает учетная запись владельца. Проверьте документацию для вашей версии, прежде чем полагаться на конкретный механизм. Главное правило одно: редактор не должен быть открыт без входа, поэтому создайте владельца сразу после запуска.
Резервные копии базы и данных
Для n8n важны две части. Первая - база PostgreSQL: сценарии, учетные данные в зашифрованном виде и история выполнений. Вторая - каталог /home/node/.n8n в томе n8n_data, где лежат служебные файлы n8n. Ключ шифрования хранится отдельно, и без него база не даст восстановить сохраненные учетные данные.
cd ~/n8n
mkdir -p backups
docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > backups/n8n-db-$(date +%F).sql.gz
docker run --rm -v n8n_n8n_data:/data:ro -v "$(pwd)/backups":/backup alpine tar czf /backup/n8n-data-$(date +%F).tar.gz -C /data .Имя тома зависит от имени каталога проекта: в примере каталог называется n8n, поэтому том получает имя n8n_n8n_data. Точное имя проверьте командой docker volume ls.
Копии храните вне сервера: в S3-совместимом хранилище, на другом VPS или у себя локально. Бэкап на том же диске не спасет, если сломается сам сервер. Раз в месяц проверяйте восстановление на тестовом стенде: копия, которую никогда не разворачивали, остается предположением.
Восстановление базы выполняется обратной командой: поднимите PostgreSQL из compose, затем передайте дамп через gunzip -c backups/n8n-db-ДАТА.sql.gz и docker compose exec -T postgres psql -U n8n -d n8n. Перед восстановлением остановите n8n командой docker compose stop n8n.
Обновление n8n
Перед обновлением сделайте свежий бэкап. Затем загрузите новый образ и пересоздайте контейнеры:
cd ~/n8n
docker compose pull
docker compose up -d
docker compose logs --tail=50 n8nКрупные версии могут менять поведение отдельных узлов и миграции базы. Читайте релиз-ноты перед обновлением, после запуска проверяйте ключевые сценарии и только потом считайте обновление успешным. Если что-то пошло не так, вернитесь на предыдущий тег в docker-compose.yml и восстановите базу из бэкапа, если миграция уже прошла.
Безопасность self-hosted n8n
- Не публикуйте порты 5678 и 5432 наружу. В описанной конфигурации PostgreSQL вообще не имеет секции ports.
- Храните .env с правами 600 и не коммитьте его в git.
- Давайте API-ключам, подключенным в n8n, только те права, которые нужны сценарию.
- Не храните в сценариях пароли открытым текстом: используйте credentials n8n.
- Обновляйте систему и Docker, а базовые меры защиты сервера описаны в статье Безопасность Linux-сервера.
Частые проблемы при установке
- Webhook-и показывают http вместо https: проверьте WEBHOOK_URL и N8N_PROTOCOL, затем пересоздайте контейнер командой docker compose up -d.
- Редактор открывается, но не обновляется: чаще всего в nginx не хватает заголовков Upgrade и Connection.
- n8n не стартует и пишет ошибку подключения к базе: проверьте пароль в .env и статус контейнера postgres.
- certbot не выпускает сертификат: домен должен указывать на IP сервера, а порты 80 и 443 быть доступны снаружи.
Если сценарий работает в редакторе, но не срабатывает по webhook-у, первым делом проверьте публичный адрес в WEBHOOK_URL и доступность домена извне.