У меня была задача, сделать reverse proxy, который будет проксировать трафик и для определённых доменов выпускать новые сертификаты налету, а для некоторых нужно просто автоматически выпустить сертификат.
Для такой задачи идеально подходит Caddy.
Что такое Caddy?
Caddy - веб-сервер с открытым исходным кодом и автоматическим HTTPS, написанный на Go

Сертификат для статичных доменов
Для работы с Caddy нужно создать Caddyfile
{
# Укажите email для уведомлений по SSL-сертификатам
email caddy@email.com
}
Это минимальный набор, который нужен для того, что бы Caddy запустился. Сначала разберемся со статичными доменами. Для того что бы Caddy запросил сертификат для таких доменов, нужно просто добавить эти домены в конфиг.
{
email caddy@email.com
}
# Указываем домен
my-site.com {
# Указываем куда проксировать
reverse_proxy http://localhost:3000 {
header_up Host {upstream_hostport}
}
}
Вот и все, при старте, Caddy прочитает конфиг и запустит выпуск сертификата для этого домена через Let'sEncrypt посредством http челленджа.
Как быть с wildcard?
Тут тоже все просто (особенно если у вас cloudflare). Нам нужно просто добавить wildcard домен в Caddyfile, но есть один нюанс. Вот так выглядит обновленный конфиг:
{
email caddy@email.com
}
# Указываем wildcard домен
*.my-site.com {
tls {
# даем доступ Caddy к Cloudflare DNS
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
reverse_proxy http://localhost:3000 {
header_up Host {upstream_hostport}
}
}
Когда мы используем wildcard домен в конфиге, мы обязаны использовать DNS challenge вместо http, а для этого нам нужно дать разрешение Caddy на добавление записи в DNS. В данном случае я использую Cloudflare DNS и плагин для работы с ним.
Вот и все, теперь у вас есть рабочий Reverse Proxy, который выпишет сертификат для my-site.com и wildcard *.my-site.com!
Теперь о on-demand (по требованию) сертификатах
{
email caddy@email.com
# Включает получение TLS-сертификатов по запросу.
# Можно удалить блок, если не требуется проверка доменов
# перед выдачей сертификатов
on_demand_tls {
# Проверка разрешения на выдачу сертификата для домена
# Будет вызываться перед попыткой запроса на (пере)выпуск сертификата
ask https://your-api.com/check-domain
}
}
# Это позволит обрабатывать все входящие запросы по https
https:// {
# Включаем on-demand выдачу сертификатов
tls {
on_demand
}
# Выдавать сертификаты для всех доменов, которые начинаются
# с test, то есть для таких test.* (например test.my-site.com)
@test {
header_regexp Host ^test\..*$
}
reverse_proxy @test http://localhost:3000 {
header_up Host {upstream_hostport}
}
}
Вот такой небольшой конфиг позволит автоматически выдавать сертификаты для test.* доменов. Для on-demand Caddy по умолчанию использует ZeroSSL.
А что если наш https://your-api.com/check-domain требует авторизации?
В таком случае нужна небольшая хитрость.
{
email caddy@email.com
on_demand_tls {
# Небольшая хитрость, сделаем запрос на этот же сервер, где запущен Caddy
ask http://localhost:8080/check-domain
}
}
# Это как раз то, что мы указали в on_demand_tls.ask
http://localhost:8080 {
handle_path /check-domain* {
# Endpoint в вашем реальном API
rewrite * /check-domain{uri.query}
reverse_proxy https://your-api.com {
transport http {
tls
tls_server_name your-api.com
}
header_up Host your-api.com
# Как пример можно прокинуть Header и в API проверить этот ключ
header_up X-Api-Key rjiw89wuruwriwiruwoirjw
header_up User-Agent {>User-Agent}
}
}
}
Вот такой небольшой хак, а иначе никак, ask не позволяет передать дополнительный header.
Бонус для тех кто дочитал
А для самых терпеливых у меня есть приятный бонус, пользуйтесь! Dockerfile с помощью которого можно это все запустить.
FROM caddy:2.8.4-builder AS builder
# Собираем Caddy и устанавливаем cloudflare плагин
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare
FROM caddy:2.8.4
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
# Рядом с Dockerfile должен лежать Caddyfile
COPY Caddyfile /etc/caddy/Caddyfile
RUN mkdir -p /var/www/html
WORKDIR /var/www/html
EXPOSE 80 443
# Запускаем Caddy
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
Вот и все, жду вашего отклика :) Могу написать о том, как все это залить на AWS, прежде создав инфраструктуру через AWS CloudFormation, пишите в комментах, если вам это нужно :)
А так же заглядывайте в мой Telegram-канал @devdrafts_rss, где я делюсь материалами по IT, которые сам употребляю 🙂