n8n на VPS в Docker с автоматическим HTTPS через Caddy
Установка n8n в Docker Compose за Caddy, который сам получает сертификат Let's Encrypt: домен, .env с ключом шифрования, Caddyfile, запуск, обновление и резервная копия тома. Ubuntu 24.04 и Debian 12.

n8n — платформа автоматизации, где сценарии собираются из блоков, как в Zapier или Make: вебхук → запрос к API → нейросеть → письмо. На своём сервере нет лимита запусков, а ключи от подключённых сервисов остаются у вас. Ставить будем в Docker за веб-сервером Caddy, который без единой строчки настройки получает и продлевает сертификат HTTPS.
Как устроена установка
Два контейнера. В первом работает n8n и слушает порт 5678 только внутри сети Docker. Во втором — Caddy: принимает 80 и 443, выпускает сертификат для вашего домена и передаёт запросы в n8n. Схема важна по двум причинам: без HTTPS не работают вебхуки многих сервисов (например Telegram), а порты, опубликованные Docker напрямую, открываются в обход UFW, поэтому n8n безопаснее не выставлять наружу вообще.
Вторая деталь, о которой редко пишут, — ключ шифрования. n8n хранит пароли и токены сервисов в зашифрованном виде. Потеряете ключ (например при переезде на другой сервер) — все сохранённые подключения придётся вводить заново. Поэтому зададим ключ сами и будем хранить его в .env.
Что нужно
- Сервер на tanaka.host с Ubuntu 24.04 или Debian 12 и не меньше 2 ГБ памяти — n8n сразу после запуска занимает около 370 МБ, и на 1 ГБ свободного почти не остаётся.
- Домен или поддомен на IP сервера. Для проверки без домена подойдёт бесплатный адрес вида
203-0-113-10.sslip.io— IP с дефисами вместо точек, он сам указывает на нужный сервер. - Доступ по SSH под root.
1. Направьте домен на сервер
У регистратора создайте A-запись:
| Тип | Имя | Значение |
|---|---|---|
| A | n8n |
IP вашего сервера |
Проверьте на своём компьютере:
# Должен вывести IP-адрес вашего сервера
nslookup n8n.example.com
Пока запись не разошлась, Caddy не сможет получить сертификат. Обычно это занимает от нескольких минут до часа.
2. Установите Docker
# Устанавливаем Docker официальным скриптом
curl -fsSL https://get.docker.com | sh
# Проверяем версии Docker и Compose
docker --version && docker compose version
Подробнее про варианты установки — в статье Docker на VPS.
3. Откройте брандмауэр
Если включён UFW, Caddy нужны 80 (проверка домена и редирект на HTTPS) и 443. Сначала SSH, чтобы не закрыть себе дверь:
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443
ufw enable
Правило для 443 без протокола открывает и TCP, и UDP — так заработает HTTP/3. Порт 5678 не открываем: n8n живёт за Caddy. Подробнее — UFW и firewalld.
4. Создайте папку и файл с настройками
# Папка для n8n
mkdir -p /opt/n8n && cd /opt/n8n
# Файл с настройками, ключ шифрования генерируется сразу
cat > .env <<EOF
DOMAIN=n8n.example.com
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
GENERIC_TIMEZONE=Europe/Moscow
EOF
# Файл доступен только root
chmod 600 .env
Подставьте свой домен. GENERIC_TIMEZONE — часовой пояс, по которому n8n запускает сценарии по расписанию.
Сохраните .env. Выведите его командой
cat /opt/n8n/.envи положите в менеджер паролей. БезN8N_ENCRYPTION_KEYсохранённые пароли и токены сервисов не восстановить.
5. Создайте Caddyfile
cat > /opt/n8n/Caddyfile <<'EOF'
{$DOMAIN} {
reverse_proxy n8n:5678
}
EOF
Это вся настройка. Caddy возьмёт домен из .env, получит сертификат, перенаправит HTTP на HTTPS, проставит заголовки X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto и будет проксировать WebSocket — он нужен редактору n8n.
6. Создайте docker-compose.yml
cat > /opt/n8n/docker-compose.yml <<'EOF'
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
environment:
- DOMAIN=${DOMAIN}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
n8n:
image: docker.n8n.io/n8nio/n8n:stable
restart: unless-stopped
environment:
- N8N_HOST=${DOMAIN}
- N8N_PROTOCOL=https
- N8N_PORT=5678
- N8N_WEBHOOK_URL=https://${DOMAIN}/
- N8N_PROXY_HOPS=1
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
- NODE_ENV=production
volumes:
- n8n_data:/home/node/.n8n
volumes:
caddy_data:
caddy_config:
n8n_data:
EOF
Что здесь важно:
| Переменная | Назначение |
|---|---|
N8N_HOST, N8N_PROTOCOL |
имя хоста и https, потому что пользователи приходят через Caddy по TLS |
N8N_WEBHOOK_URL |
публичный адрес вебхуков; без него n8n покажет в них localhost. В старых инструкциях это WEBHOOK_URL — работает, но считается устаревшим с n8n 2.35 |
N8N_PROXY_HOPS |
число прокси перед n8n, с Caddy — 1 |
N8N_ENCRYPTION_KEY |
ключ из .env, см. шаг 4 |
GENERIC_TIMEZONE, TZ |
пояс для расписаний и для контейнера |
У сервиса n8n нет секции ports — снаружи он доступен только через Caddy. Тома n8n_data и caddy_data переживают обновления контейнеров: в первом база SQLite со сценариями и подключениями, во втором сертификаты. Второй тоже не удаляйте: иначе Caddy при каждом пересоздании будет запрашивать новые сертификаты и упрётся в лимиты Let’s Encrypt.
7. Запустите
cd /opt/n8n
# Скачиваем образы и запускаем в фоне
docker compose up -d
# Смотрим журнал n8n, выход из просмотра по Ctrl+C
docker compose logs -f n8n
Через 20–40 секунд в журнале появится Editor is now accessible via с адресом вашего домена. В первые секунды сайт может отвечать 502, пока n8n стартует, — это нормально.
8. Сразу создайте аккаунт владельца
Откройте https://ваш-домен. n8n покажет форму Set up owner account: почта, имя, фамилия, пароль (от 8 символов, с цифрой и заглавной буквой).
Не откладывайте регистрацию. Пока владелец не создан, форму может заполнить кто угодно. Первые сканеры приходят на новый домен через секунды после выдачи сертификата — он попадает в публичные логи Certificate Transparency. Создайте аккаунт и сразу включите двухфакторную аутентификацию в настройках профиля.
Обновление
cd /opt/n8n
# Скачиваем новые образы и перезапускаем контейнеры
docker compose pull && docker compose up -d
Данные, сценарии и ключ остаются в томе и в .env. Перед переходом на новую мажорную версию (1.x → 2.x) прочитайте список изменений и сделайте копию — некоторые обновления меняют поведение нод.
Резервная копия
Всё лежит в томе Docker. Упаковываем его в архив в /root, предварительно остановив n8n для согласованности базы:
cd /opt/n8n
docker compose stop n8n
docker run --rm -v n8n_n8n_data:/data -v /root:/backup alpine tar czf /backup/n8n-backup.tar.gz -C /data .
docker compose start n8n
Compose добавляет к имени тома имя папки, поэтому том называется n8n_n8n_data; если папка другая, посмотрите docker volume ls. Скачайте /root/n8n-backup.tar.gz вместе с /opt/n8n/.env — без него архив восстановится, а пароли сервисов расшифровать не получится. Как настроить регулярную выгрузку — в статье про restic и S3.
Безопасность
- Длинный пароль владельца и 2FA.
- Не публикуйте 5678 — Docker обойдёт UFW.
- Вход на сервер по ключу, пароль отключить — инструкция.
- Вебхуки, которые запускают что-то важное, защищайте Header Auth или Basic Auth в ноде Webhook.
- Почту отправляйте через HTTPS-API провайдера (Mailgun, SendGrid, Brevo), а не SMTP-нодой: исходящие SMTP-порты у многих хостеров закрыты по умолчанию, и нода просто уйдёт в таймаут.
Если что-то не работает
502. Только что запустили — подождите минуту. Иначе docker compose logs --tail 50 n8n; на серверах с 1 ГБ частая причина — n8n не хватает памяти и он перезапускается, поможет swap или тариф побольше.
Сертификат не выпускается. docker compose logs --tail 50 caddy. Обычно домен ещё не указывает на сервер или закрыт порт 80.
В вебхуках localhost. n8n не получил N8N_WEBHOOK_URL. Проверьте переменную и домен в .env, затем docker compose up -d.
После переезда не работают подключения к сервисам. На новом сервере другой ключ шифрования. Перенесите старый .env с прежним N8N_ENCRYPTION_KEY и перезапустите n8n.
Если хотите не только n8n, а целую платформу для деплоя приложений из Git на тот же сервер, посмотрите Coolify. Документация n8n: https://docs.n8n.io.