n8n на своём сервере: установка и настройка
Установка n8n на свой сервер через Docker Compose: PostgreSQL, домен с HTTPS, ключ шифрования, вебхуки, queue mode, бэкапы и обновления без потери данных.
Ниже — схема для одного VPS: n8n, PostgreSQL и task runners в Docker Compose, перед ними Caddy или nginx. Всё сверено с документацией и кодом n8n и актуально на сентябрь 2026 года: stable — 2.41.4, beta — 2.42.1, n8n 3.0 запланирован на октябрь.
Что понадобится
- VPS ForestsNet Cloud на Ubuntu 22.04/24.04 или Debian 11/12: от 1 vCPU и 2 ГБ RAM для личного инстанса, от 2 vCPU и 4 ГБ для рабочего.
- Docker с плагином Compose v2: «Docker и Docker Compose».
- Поддомен вроде
n8n.example.comс A-записью на IP сервера: «Как привязать домен к серверу». - Caddy или nginx на хосте.
- Вход по SSH-ключу: «Усиление SSH».
Шаг 1. Решите, подходит ли вам self-hosted n8n
Что вы получаете
n8n — конструктор автоматизаций: сценарий (workflow) собирается из узлов и запускается вебхуком, расписанием или событием сервиса, есть узел Code на JavaScript и Python, AI-агенты и MCP. Своя установка не ограничивает число сценариев и запусков, а credentials остаются на вашем диске. Обновления, бэкапы и безопасность — тоже на вас.
Лицензия
n8n выходит под Sustainable Use License — это fair-code, а не open source. Бесплатно можно автоматизировать свою компанию и личные проекты, делать сценарии для клиентов на своём инстансе и брать деньги за разработку, если клиенты сами сценарии не правят. Без договора с n8n нельзя сдавать его как сервис, где клиенты строят сценарии, в том числе через ваш интерфейс, API или AI-агента, и продавать n8n под своим брендом.
Чего нет в Community Edition
Queue mode с воркерами в бесплатной редакции есть. Нет SSO через SAML и LDAP, проектов с ролями, окружений и Git, внешних хранилищ секретов, стриминга логов, хранения файлов в S3, multi-main и принудительной 2FA для всех. Главное для команды: сценарии и credentials видят только владелец инстанса и их автор, общего доступа нет. Бесплатная регистрация по email добавляет папки, отладку прошлых запусков и custom execution data.
Шаг 2. Подготовьте сервер
Снаружи нужны только порты 22, 80 и 443, подробнее — в «Файрвол ufw: порты».
sudo ufw allow 22/tcp
sudo ufw allow 80,443/tcp
sudo ufw enableШаг 3. Создайте .env с секретами
sudo mkdir -p /opt/n8n && cd /opt/n8n
sudo tee .env > /dev/null <<EOF
N8N_VERSION=2.41.4
N8N_DOMAIN=n8n.example.com
GENERIC_TIMEZONE=Europe/Moscow
POSTGRES_PASSWORD=$(openssl rand -hex 24)
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
N8N_RUNNERS_AUTH_TOKEN=$(openssl rand -hex 32)
EOF
sudo chmod 600 .envN8N_ENCRYPTION_KEY шифрует все credentials в базе. Если его не задать, n8n сгенерирует ключ сам и сохранит в /home/node/.n8n/config внутри тома: потеряли том — credentials в уцелевшей базе уже не расшифровать. Сразу сохраните копию .env вне сервера.
Шаг 4. Опишите сервисы в compose.yml
Создайте /opt/n8n/compose.yml:
x-n8n-env: &n8n-env
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: ${N8N_DOMAIN}
N8N_PROTOCOL: https
N8N_EDITOR_BASE_URL: https://${N8N_DOMAIN}/
N8N_WEBHOOK_URL: https://${N8N_DOMAIN}/
N8N_PROXY_HOPS: 1
GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
TZ: ${GENERIC_TIMEZONE}
N8N_RUNNERS_MODE: external
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0
EXECUTIONS_DATA_MAX_AGE: 168
EXECUTIONS_DATA_PRUNE_MAX_COUNT: 20000
services:
postgres:
image: postgres:18
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
PGDATA: /var/lib/postgresql/data
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment: *n8n-env
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
runners:
image: n8nio/runners:${N8N_VERSION}
restart: unless-stopped
environment:
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_TASK_BROKER_URI: http://n8n:5679
depends_on:
- n8n
volumes:
db_data:
n8n_data:Что здесь важно:
- Версия зафиксирована.
n8nio/n8nиn8nio/runnersобязаны быть одной версии, а с тегомlatestлюбойdocker compose pullпринесёт новую версию с миграциями базы. - Каталог данных PostgreSQL задан явно. В
postgres:18он переехал, и без строкиPGDATAбаза окажется вне тома. - Адреса.
N8N_WEBHOOK_URL— база для вебхуков, без него редактор покажетhttp://localhost:5678/webhook/...;N8N_EDITOR_BASE_URLнужен письмам и OAuth. Прежнее имяWEBHOOK_URLс версии 2.35 устарело. - Прокси.
N8N_PROXY_HOPS: 1велит брать IP клиента изX-Forwarded-For. Если перед nginx есть ещё Cloudflare с проксированием, ставьте2. - Часовой пояс. Без
GENERIC_TIMEZONEрасписания идут поAmerica/New_York. - Task runners. С 2.0 код из узла Code выполняется отдельно от n8n. По умолчанию это дочерний процесс с правами n8n (устаревший internal mode), а контейнер
runnersотделяет код от базы и ключа и нужен для Python.
Запустите стек и проверьте готовность:
cd /opt/n8n
sudo docker compose up -d
sudo docker compose ps
curl -s http://127.0.0.1:5678/healthz/readiness/healthz/readiness вернёт {"status":"ok"}, когда база подключена и миграции прошли. Логи — sudo docker compose logs -f n8n, а для внешнего мониторинга подойдёт https://n8n.example.com/healthz, например в Uptime Kuma.
Шаг 5. Подключите домен и HTTPS
Вариант А. Caddy
Caddy сам выпустит сертификат, проксирует WebSocket и передаст Host и X-Forwarded-*. Добавьте в /etc/caddy/Caddyfile:
n8n.example.com {
reverse_proxy 127.0.0.1:5678
}Примените: sudo systemctl reload caddy. Подробнее — в «Caddy: автоматический HTTPS».
Вариант Б. Nginx и certbot
По умолчанию nginx не пропускает WebSocket, передаёт в Host адрес бэкенда, ограничивает тело запроса 1 МБ и ждёт ответа 60 секунд — n8n это мешает. Создайте /etc/nginx/sites-available/n8n.example.com:
server {
listen 80;
server_name n8n.example.com;
client_max_body_size 64m;
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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_buffering off;
proxy_read_timeout 3600s;
}
}Включите сайт и получите сертификат, подробнее — в «Бесплатный SSL с Let's Encrypt (certbot)»:
sudo ln -s /etc/nginx/sites-available/n8n.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d n8n.example.comЧто делают строки конфига:
- WebSocket. Заголовки
UpgradeиConnectionпропускают/rest/push, по которому редактор получает результаты запусков. - Проверка Origin. Ей нужны
HostиX-Forwarded-Host: увидев127.0.0.1:5678, n8n отклонит WebSocket редактора. - Размер запроса.
client_max_body_sizeснимает лимит в 1 МБ, а сам n8n принимает до 16 МиБ (N8N_PAYLOAD_SIZE_MAX), файлы в multipart — до 200 МиБ. - Таймаут.
proxy_read_timeoutне даёт оборвать долгий вебхук и WebSocket, который n8n пингует раз в 60 секунд. - Буферизация. С
proxy_buffering offпотоковые ответы AI-агентов доходят до клиента сразу.
Шаг 6. Первый вход: владелец, 2FA, порты
Откройте https://n8n.example.com: n8n предложит создать владельца (owner), и кто первым заполнит форму, тот и получит инстанс. Регистрируйтесь сразу после запуска, затем включите 2FA в Settings → Personal → Enable 2FA и сохраните коды восстановления.
Если коды потеряны или забыт пароль:
sudo docker compose exec n8n n8n mfa:disable [email protected]
sudo docker compose exec n8n n8n user-management:resetПервая снимает 2FA с пользователя. Вторая удаляет остальных пользователей, передаёт их сценарии и credentials владельцу и сбрасывает его учётную запись до экрана создания — выход для владельца без SMTP (N8N_EMAIL_MODE=smtp и N8N_SMTP_*). Остальным владелец выдаёт ссылку сброса пароля в Settings → Users.
Проверьте порты:
sudo ss -tlnp | grep -E '5678|5679|5432'В выводе должна быть одна строка с 127.0.0.1:5678. Общий список мер — в «Чеклисте базовой защиты VPS».
Шаг 7. Настройте вебхуки
У каждого узла Webhook два адреса:
- Тестовый
/webhook-test/<path>слушает 120 секунд после Listen for test event и принимает один вызов, данные видны на холсте. - Рабочий
/webhook/<path>работает после Publish. С версии 2.0 правки остаются черновиком, а в работе — опубликованная версия, так что после изменений сценарий публикуют заново. Запуски видны во вкладке Executions.
Кроме /webhook/, наружу должны смотреть /webhook-waiting/ (сценарии, ждущие ответа, например одобрения в Slack), /form/ и /form-waiting/. Публичные вебхуки закрывайте аутентификацией узла: Basic, Header или JWT. Фильтр IP-адресов в узле работает только с N8N_PROXY_HOPS.
Шаг 8. Учтите, как работает узел Code
- Python доступен только через контейнер runners. Это нативный Python 3 вместо Pyodide, поэтому
_inputи доступ к полям через точку из старых сценариев не работают. - Переменные окружения закрыты:
$envв выражениях и Code недоступен (N8N_BLOCK_ENV_ACCESS_IN_NODE=true), секреты храните в credentials. - Сторонние модули ставятся в свой образ
FROM n8nio/runners:2.41.4черезpnpm addилиuv pip installи разрешаются в/etc/n8n-task-runners.jsonключамиNODE_FUNCTION_ALLOW_EXTERNALиN8N_RUNNERS_EXTERNAL_ALLOW. - Таймаут кода — 300 секунд (
N8N_RUNNERS_TASK_TIMEOUT), в 3.0 станет 60. - Execute Command и Local File Trigger выключены через
NODES_EXCLUDE. Вернув их, вы дадите shell в контейнере всем, кто правит сценарии. - Файловые узлы видят только
/home/node/.n8n-files, а этот каталог вне тома. Смонтируйте свой, например./files:/files, и задайтеN8N_RESTRICT_FILE_ACCESS_TO=/files.
Шаг 9. Включите queue mode, если одного процесса мало
В обычном режиме один процесс Node.js отдаёт интерфейс, принимает вебхуки и выполняет сценарии: тяжёлый сценарий тормозит всё остальное, а лишние ядра простаивают. Сначала попробуйте N8N_CONCURRENCY_PRODUCTION_LIMIT — запуски сверх лимита встанут в очередь. Если мало, включайте queue mode: главный процесс кладёт задания в Redis, воркеры их выполняют. OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS шлёт туда же запуски из редактора.
Добавьте в x-n8n-env:
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_HEALTH_CHECK_ACTIVE: "true"
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS: "true"В services добавьте Redis и пару из воркера и его runners, в volumes — redis_data:, в depends_on сервиса n8n — redis с condition: service_healthy:
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 10
worker-1:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: unless-stopped
command: worker --concurrency=10
environment: *n8n-env
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- n8n
runners-1:
image: n8nio/runners:${N8N_VERSION}
restart: unless-stopped
environment:
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_TASK_BROKER_URI: http://worker-1:5679
depends_on:
- worker-1Что учесть:
- Ключ шифрования воркер берёт из того же
x-n8n-env: без ключа он не стартует, с другим не расшифрует credentials. - Runners у каждого воркера свои, ведь брокер задач живёт в воркере. Поэтому
--scaleне подходит: добавляйте парыworker-2иrunners-2. - Параллелизм.
--concurrency— одновременные запуски на воркер, по умолчанию 10. Меньше 5 не советуют: много таких воркеров исчерпают пул соединений к базе. - Файлы из сценариев хранятся в PostgreSQL, до 512 МиБ на файл:
filesystemв queue mode не поддерживается, а S3 есть только в платных планах. - Redis не публикуйте и не включайте в нём вытеснение ключей вроде
allkeys-lru, иначе пропадут задания. Подробнее — в «Redis: установка и настройка».
Шаг 10. Настройте обслуживание
Очистка истории выполнений
По умолчанию n8n хранит запуски 14 дней и не больше 10 000, в compose выше — 7 дней и 20 000. Удаляются они вместе с бинарными данными, аннотированные и незавершённые не трогаются. Писать меньше помогут EXECUTIONS_DATA_SAVE_ON_SUCCESS=none, чтобы хранить только ошибки, и EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=false, а для отдельного сценария — его настройки.
PostgreSQL место удалённых строк системе не возвращает. Проверьте, что выросло:
sudo docker compose exec postgres psql -U n8n -d n8n -c "SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) FROM pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 5;"Обычно это execution_data. Сжать таблицу может только VACUUM FULL: он блокирует её и требует свободного места размером с неё, поэтому остановите n8n (sudo docker compose stop n8n), а после запустите снова (start):
sudo docker compose exec postgres psql -U n8n -d n8n -c "VACUUM (FULL, ANALYZE) execution_data;"Ещё растут бинарные данные в томе n8n и логи Docker — задайте max-size и max-file в /etc/docker/daemon.json, см. «Закончилось место на диске».
Бэкап
Нужны три вещи: дамп базы, ключ из .env и том n8n_data с файлом config, бинарными данными и community nodes. Без ключа дамп бесполезен.
sudo mkdir -p /var/backups/n8n && cd /opt/n8n
sudo docker compose exec -T postgres pg_dump -U n8n -d n8n -Fc | sudo tee /var/backups/n8n/db-$(date +%F).dump > /dev/null
sudo docker run --rm -v n8n_n8n_data:/data:ro -v /var/backups/n8n:/backup alpine tar czf /backup/n8n-data-$(date +%F).tgz -C /data .
sudo cp .env /var/backups/n8n/env-$(date +%F)Имя тома — n8n_n8n_data, по каталогу проекта; проверьте через sudo docker volume ls. Расписание и копии вне сервера — в статьях «Бэкапы баз данных», «Автобэкапы по расписанию (cron)» и «Инкрементальные бэкапы с restic». Хотя бы раз восстановите бэкап на чистом сервере. CLI-экспорт n8n export:workflow --backup его не заменяет: в нём нет пользователей, истории и переменных.
Обновления
Минорные версии выходят почти еженедельно, исправления безопасности — раз в две недели.
- Прочитайте release notes до целевой версии, а перед мажорной откройте Settings → Migration Report.
- Снимите бэкап.
- Смените
N8N_VERSIONв.envи выполнитеsudo docker compose pull && sudo docker compose up -d. - Не останавливайте контейнер, пока в логе видно
Migrations in progress, please do NOT stop the process.
Миграции необратимы: откат — это старая версия плюс дамп. Main, воркеры и runners держите на одной версии. Расписания по умолчанию живут в памяти, и запуск, пришедшийся на рестарт, пропадёт; с версии 2.36 это решает durable scheduler (N8N_SCHEDULER_ENABLED=true и N8N_USE_WORKFLOW_PUBLICATION_SERVICE=true).
Что изменит n8n 3.0:
- только Docker, установка через npm перестанет работать;
~/.n8n/binaryDataстанет~/.n8n/storage— поправьте тома, смонтированные прямо наbinaryData;- непроверенные community nodes не загрузятся без
N8N_UNVERIFIED_PACKAGES_ENABLED=true; - таймаут Code сократится до 60 секунд;
- ротация ключей шифрования включится по умолчанию, и откат на 2.x останется только из дампа;
- уйдут старые узлы Function, Cron, Read Binary File и другие — их покажет Migration Report.
Шаг 11. Закройте основные риски
- Обновляйтесь вовремя. За 2026 год n8n выпустил 196 бюллетеней безопасности, 19 из них критические. Ni8mare (CVE-2026-21858, CVSS 10) позволяла без входа читать файлы сервера через формы и захватить инстанс, исправлена в 1.121.0. CVE-2025-68613 — выполнение кода любым вошедшим пользователем — с марта 2026 года в каталоге CISA KEV, то есть эксплуатируется.
- Community nodes работают с правами n8n и видят все credentials. В январе 2026 года Endor Labs нашла в npm пакеты
n8n-nodes-*под видом интеграций (один изображал Google Ads), которые крали OAuth-токены. Ставьте только проверенные (verified) узлы или выключите установку:N8N_COMMUNITY_PACKAGES_ENABLED=false. - Редактор надёжнее открыть только из VPN или с доверенных IP через
allowиdenyв nginx, оставив публичными пути из Шага 7. - Лишнее выключите: публичный API —
N8N_PUBLIC_API_DISABLED=true. Если сценарии пишут другие люди, включитеN8N_SSRF_PROTECTION_ENABLED=true(с 2.12), и узлы перестанут ходить на приватные адреса и соседние контейнеры. - Аудит:
sudo docker compose exec n8n n8n auditнайдёт неиспользуемые credentials и рискованные узлы.
Сколько ресурсов нужно
В обычном режиме n8n — один процесс Node.js на одном ядре. Официальный Helm-чарт закладывает на главный процесс и воркер от 512 МБ до 1 ГБ памяти, на runners — от 256 до 512 МБ. Память растёт с объёмом данных в выполнении, а ручной запуск держит их копию ещё и для редактора.
- 1 vCPU и 2 ГБ — личный инстанс: десятки сценариев на расписаниях и вебхуках, редкий Code.
- 2 vCPU и 4 ГБ — рабочий инстанс: AI-агенты, Code, выборки на тысячи строк, файлы. Столько же официальная инструкция требует для стека с песочницей n8n Assistant.
- 4 vCPU и 8 ГБ и больше — queue mode с двумя-тремя воркерами.
Диск — NVMe от 20 ГБ: каждый запуск пишет в execution_data.
Трафик n8n почти не тратит. Вебхуки, ответы API, docker pull, apt и npm — входящий трафик, а в пакет ForestsNet Cloud засчитывается только исходящий: запросы n8n к API и ответы на вебхуки, обычно килобайты. Заметным он становится, если сценарии отправляют наружу файлы.
Диагностика
- Плашка Connection lost. WebSocket
/rest/pushне проходит: нетUpgradeиConnection, подменёнHost(в логе —Origin header does NOT match the expected origin) или короткий таймаут, см. Шаг 5. - Адрес вебхука с localhost. Не задан
N8N_WEBHOOK_URL: добавьте его и выполнитеsudo docker compose up -d. - Ошибка X-Forwarded-For.
ValidationError: The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false— не заданN8N_PROXY_HOPS. - Страница о secure cookie.
Your n8n server is configured to use a secure cookie, however you are either visiting this via an insecure URL, or using Safari.— вход поhttp://. Настройте HTTPS, а до того заходите через SSH-туннель наlocalhost:5678не из Safari;N8N_SECURE_COOKIE=false— только для проверки. - Credentials не расшифровываются.
Credentials could not be decrypted— том пересоздан безN8N_ENCRYPTION_KEYили ключ заменён. Верните старый ключ из бэкапа, иначе credentials вводятся заново. - Нет прав на config.
EACCES: permission denied, open '/home/node/.n8n/config'— каталог хоста принадлежит root, а n8n работает под uid 1000:sudo chown -R 1000:1000 <каталог>. - Вебхук отвечает 404.
The requested webhook "POST <path>" is not registered.— сценарий не опубликован, истёк тестовый режим или импорт через CLI снял публикацию;This webhook is not registered for GET requests— не тот метод. - Не хватает памяти.
n8n may have run out of memory while running this executionили рестарты контейнера. Код выхода вsudo docker compose ps -a: 137 — OOM killer, 134 — лимит кучи V8. Дробите данные через Loop Over Items и sub-workflows, добавьте RAM или поднимитеNODE_OPTIONS=--max-old-space-size=2048. - Code не выполняется.
Task request timed outилиPython runner unavailable— runners не подключились: разные версии образов или токены, нетN8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0. Смотритеsudo docker compose logs runners. - PostgreSQL не стартует после смены тега.
database files are incompatible with server— мажорную версию меняют черезpg_dumpallи восстановление в новый том, данные целы.
Источники
- Документация n8n: установка через Docker Compose, вебхуки за обратным прокси, переменные окружения, task runners, queue mode, история выполнений, ошибки памяти, бэкап и восстановление
- Лицензия и редакции: сравнение редакций, FAQ по лицензии
- Изменения: breaking changes n8n 2.0, breaking changes n8n 3.0, релизы на GitHub, примеры Compose n8n-io/n8n-hosting
- Безопасность: бюллетени n8n, Cyera — Ni8mare, NVD — CVE-2025-68613, CISA KEV, Endor Labs — вредоносные community nodes
- Хост и прокси: Docker и ufw, Caddy — reverse_proxy, PostgreSQL — VACUUM
- Сообщество: Connection lost и заголовок Host, Хабр: «n8n self-hosted в production: docker-compose, nginx, ретраи и три грабли», «Три воркера n8n ждали четвёртого», «Как обновить n8n на своем сервере (Docker)»