n8n за Nginx, Traefik и Cloudflare Tunnel: HTTPS, webhooks и OAuth без localhost ¶
Обновлено: 2026-05-29
Reverse proxy для n8n нужен не ради “красивого домена”, а чтобы внешние сервисы стабильно доставляли webhook, OAuth-провайдеры видели правильный redirect URL, а пользователи открывали редактор по HTTPS. Если n8n внутри Docker слушает 5678, а наружу выходит домен на 443, нельзя оставлять n8n гадать адрес самому: задайте публичный URL явно.
Эта инструкция разбирает три практичных варианта: Nginx, Traefik и Cloudflare Tunnel. Для VPS с публичным IP чаще всего берут Nginx или Traefik. Для домашнего сервера, QNAP, Raspberry Pi или офиса без белого IP удобнее Cloudflare Tunnel, потому что cloudflared сам устанавливает исходящее соединение к Cloudflare.
Быстрый выбор: Nginx, Traefik или Cloudflare Tunnel ¶
| Вариант | Когда выбирать | Что важно проверить |
|---|---|---|
| Nginx | Один VPS, понятный конфиг, ручной контроль | proxy_set_header X-Forwarded-Proto https, размер body, timeout |
| Traefik | Несколько Docker-сервисов и автоматический Let’s Encrypt | labels, network, router/service, entrypoints |
| Cloudflare Tunnel | Нет публичного IP или нужен доступ без открытых портов | published hostname, Zero Trust policies, корректный service URL |
Обязательные переменные n8n ¶
Минимальный набор для домена https://n8n.example.ru:
N8N_HOST=n8n.example.ru
N8N_PROTOCOL=https
N8N_PORT=5678
WEBHOOK_URL=https://n8n.example.ru/
N8N_PROXY_HOPS=1
N8N_EDITOR_BASE_URL=https://n8n.example.ru/
GENERIC_TIMEZONE=Europe/Moscow
WEBHOOK_URL особенно важен для production webhook. Если он пустой или указывает на localhost, Telegram, Tilda, ЮKassa, amoCRM и Bitrix24 будут получать неправильный адрес. После изменения env перезапустите контейнеры и откройте любую Webhook node: production URL должен начинаться с публичного домена.
Nginx: минимальный конфиг для n8n ¶
server {
listen 80;
server_name n8n.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name n8n.example.ru;
ssl_certificate /etc/letsencrypt/live/n8n.example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.example.ru/privkey.pem;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
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 https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
Если n8n работает в Docker-сети, вместо 127.0.0.1:5678 используйте имя сервиса и общую сеть. Для больших файлов поднимите client_max_body_size, но не делайте его безлимитным: лучше ограничить размер входящих файлов на уровне бизнес-процесса.
Traefik: Docker labels без отдельного nginx.conf ¶
services:
n8n:
image: n8nio/n8n:latest
env_file: .env
networks: [web]
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(`n8n.example.ru`)
- traefik.http.routers.n8n.entrypoints=websecure
- traefik.http.routers.n8n.tls.certresolver=letsencrypt
- traefik.http.services.n8n.loadbalancer.server.port=5678
networks:
web:
external: true
Traefik удобен, когда на одном сервере живут n8n, Supabase, MinIO, NocoDB и другие сервисы. Но labels сложнее отлаживать, чем один nginx-конфиг. Если домен открывает 404 Traefik, сначала проверьте, что контейнер подключён к той же Docker network, что и Traefik.
Cloudflare Tunnel: когда сервер не должен принимать входящие порты ¶
services:
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN}
restart: unless-stopped
n8n:
image: n8nio/n8n:latest
env_file: .env
restart: unless-stopped
В Cloudflare Zero Trust добавьте published application: hostname n8n.example.ru, service http://n8n:5678 или http://localhost:5678 в зависимости от сети контейнеров. Для редактора n8n можно включить Cloudflare Access, но production webhook для внешних сервисов не должен требовать интерактивный login, иначе webhooks перестанут доходить.
Smoke-test после настройки ¶
- Откройте
https://n8n.example.ruв браузере, проверьте отсутствие mixed content. - Создайте Webhook node с методом POST и скопируйте production URL.
- Активируйте workflow и отправьте тест:
curl -i -X POST https://n8n.example.ru/webhook/proxy-smoke-test \
-H 'Content-Type: application/json' \
-d '{"source":"curl","check":"reverse-proxy"}'
- Проверьте execution в n8n: должен быть виден входящий JSON.
- Откройте credentials OAuth-сервиса и убедитесь, что redirect URL начинается с публичного домена.
Типовые ошибки ¶
| Симптом | Вероятная причина | Что сделать |
|---|---|---|
| Webhook URL содержит localhost | не задан WEBHOOK_URL | добавить env, перезапустить n8n |
| OAuth redirect mismatch | провайдер видит другой домен/протокол | проверить N8N_EDITOR_BASE_URL, WEBHOOK_URL, callback в кабинете сервиса |
| 413 Payload Too Large | proxy режет размер запроса | поднять лимит body и ограничить бизнес-логикой |
| 502 Bad Gateway | proxy не видит контейнер n8n | проверить Docker network, port 5678, health контейнера |
| 504 Gateway Timeout | workflow отвечает слишком долго | вернуть быстрый ответ через Respond to Webhook, долгую работу вынести после ответа |
Связанные инструкции ¶
- WEBHOOK_URL и HTTPS в n8n
- Nginx для n8n
- Traefik для n8n
- Cloudflare Tunnel для n8n
- Диагностика webhook
Production-чеклист для reverse proxy
Используйте этот блок как быстрый контроль перед публикацией workflow или изменением существующей автоматизации. Он не заменяет staging, но помогает поймать самые частые отказы заранее.
- Перед запуском: проверить HTTPS, X-Forwarded-* headers, body size, timeout и WEBHOOK_URL.
- Минимальный тест: вызвать production webhook извне и сверить URL в execution data.
- Типовой отказ: n8n генерирует внутренний localhost URL вместо публичного домена.
- Что логировать: входной payload без секретов, статус внешнего API, branch ошибки, execution id и владельца процесса.
Критерий готовности: сценарий проходит успешный путь, ошибочный путь и повтор события без дублей, потери данных и неконтролируемого падения execution.
Операционный runbook для self-hosted ¶
Для темы «n8n за Nginx, Traefik и Cloudflare Tunnel» важно разделять настройку и эксплуатацию. Настройка отвечает на вопрос “запустилось ли”, эксплуатация — “сможем ли мы восстановиться, обновиться и расследовать инцидент без потери credentials и execution history”.
Перед изменениями проверьте бэкап базы, значение N8N_ENCRYPTION_KEY, состояние volume, логи web-процесса и worker-процесса. Главный риск — случайно расширить права credentials, сохранить секреты в логах или отдать действие без approval.
| Слой | Что зафиксировать | Зачем |
|---|---|---|
| Вход | payload webhook/API с подписью, timestamp, event_id и исходным HTTP-статусом | позволяет повторить проблему без доступа к production-секретам |
| Контроль | restart_count, memory_usage, queue_depth, worker_concurrency, failed_executions | показывает деградацию раньше, чем пользователи начинают писать в поддержку |
| Безопасность | случайно расширить права credentials, сохранить секреты в логах или отдать действие без approval | снижает риск скрытых дублей, утечки данных и неконтролируемых write-действий |
| Готовность | есть тест на happy path, пустой вход, повтор и сбой внешнего сервиса для «n8n за Nginx, Traefik и Cloudflare Tunnel» | делает статью пригодной для runbook, а не только для чтения |
Пример безопасного входного контракта ¶
docker compose ps
docker compose logs --tail=200 n8n
docker compose logs --tail=200 n8n-worker
printenv | grep -E 'N8N_|WEBHOOK_|DB_|QUEUE_'
# перед изменениями: backup базы + проверка N8N_ENCRYPTION_KEY
Критерий готовности ¶
- есть свежий backup базы и проверено значение N8N_ENCRYPTION_KEY
- web, worker, queue и database используют согласованные переменные окружения
- после изменения проверены логи, healthcheck и запуск критичных workflow
- записан rollback-план с командами и ответственным