453 слов | 3 минуты

Caddy как reverse proxy для вебхуков перед n8n

Задача: принимать вебхуки от внешнего сервиса на отдельном поддомене и порту, проксировать их в n8n, а всё остальное закрывать 404. TLS-сертификат должен выпускаться и продлеваться автоматически.

Зачем отдельный reverse proxy перед n8n

  • Внешний сервис стучится на свой собственный домен/порт, а не напрямую в n8n — так проще ограничить доступ только к нужному пути (/webhook/*).
  • Caddy сам получает и продлевает сертификат Let's Encrypt — не нужен отдельный certbot.
  • Запросы не по нужному пути сразу получают 404, не долетая до n8n.

Шаг 1. Подключение официального репозитория Caddy

В штатном репозитории Ubuntu пакет Caddy либо отсутствует, либо устаревший, поэтому используем официальный репозиторий Cloudsmith:

sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update

Проверка: в выводе последнего apt update должна быть строка вида Get:N https://dl.cloudsmith.io/public/caddy/stable/deb/... InRelease без ошибок — значит репозиторий подключился и список пакетов забрался корректно.

Шаг 2. Установка пакета

sudo apt install -y caddy

После установки пакет автоматически:

  • кладёт бинарник в /usr/bin/caddy;
  • создаёт systemd-юнит /lib/systemd/system/caddy.service;
  • создаёт системного пользователя caddy, от имени которого работает сервис;
  • создаёт дефолтный конфиг /etc/caddy/Caddyfile с заглушкой на 80-м порту;
  • сразу запускает сервис и включает его в автозагрузку.

То есть сразу после apt install Caddy уже слушает 80-й порт с заглушкой — это нормально, но мешает аккуратно положить свой конфиг.

Шаг 3. Остановка сервиса перед правкой конфига

sudo systemctl stop caddy
sudo systemctl status caddy --no-pager

Ожидаемый результат: Active: inactive (dead) — сервис установлен корректно, но временно не запущен. Это нужно, чтобы спокойно заменить Caddyfile, не оставляя заглушку висеть на порту.

Перед заменой конфига полезно посмотреть, что лежит в нём по умолчанию:

cat /etc/caddy/Caddyfile

Шаг 4. Свой Caddyfile

Конфиг ниже: домен webhook.example.ru на порту 8443 принимает запросы только по пути /webhook/* и проксирует их в n8n; всё остальное получает 404. Подставьте свой домен и адрес n8n.

sudo tee /etc/caddy/Caddyfile > /dev/null << 'EOF'
{
	email info@example.ru
	auto_https disable_redirects
}

webhook.example.ru:8443 {
	handle /webhook/* {
		reverse_proxy https://n8n.example.ru {
			header_up Host n8n.example.ru
		}
	}
	handle {
		respond 404
	}
}
EOF

Проверка синтаксиса перед запуском:

sudo caddy validate --config /etc/caddy/Caddyfile

Шаг 5. Запуск и выпуск сертификата

sudo systemctl start caddy

Сразу после старта смотрим логи:

sudo journalctl -u caddy -f --no-pager

В течение 5–30 секунд Caddy должен:

  1. открыть порт 8443;
  2. определить, что для домена нужен сертификат;
  3. обратиться к Let's Encrypt;
  4. пройти проверку TLS-ALPN-01 — Let's Encrypt сам подключается на домен:8443 и проверяет специальный ALPN-ответ (поэтому порт должен быть доступен снаружи именно на этом этапе).

Особенности TLS-ALPN-01 на нестандартном порту

Момент Почему важно
Порт указан явно в адресе сайта (:8443) Caddy и Let's Encrypt должны проверять сертификат именно на этом порту
auto_https disable_redirects Отключает автоматический редирект с HTTP на HTTPS — нужен, если 80-й порт не используется этим сайтом
Порт должен быть открыт снаружи в момент выпуска Без доступа извне challenge не пройдёт и сертификат не выпустится
handle { respond 404 } Любой путь кроме /webhook/* не должен доходить до n8n

Выводы

  1. Caddy ставится из стороннего репозитория Cloudsmith, штатный репозиторий Ubuntu для этого не подходит.
  2. После установки сервис сразу активен с конфигом-заглушкой — перед правкой конфига его стоит остановить.
  3. Один Caddyfile может одновременно ограничивать доступ по пути (handle /webhook/*) и закрывать всё остальное 404.
  4. Сертификат Let's Encrypt на нестандартном порту выпускается через TLS-ALPN-01 — порт должен быть доступен снаружи именно в момент первого запуска.
  5. После успешного запуска проверка по логам через journalctl -u caddy -f показывает весь процесс выпуска сертификата в реальном времени.