Переехал с nginx на Caddy — и перестал руками возиться с сертификатами
У меня на сервере крутится с десяток сервисов: медиатека, заметки, файлопомойка, пара админок. Все они слушают свои порты, а наружу торчит один реверс-прокси, который разруливает, кого куда пускать по доменному имени. Долгое время этим занимался nginx. Работал, не жаловался — но обслуживать его конфиги и сертификаты надоело настолько, что я в один выходной взял и переехал на Caddy.
Что бесило в nginx
Сам по себе nginx прекрасен, вопросов нет. Но вокруг него я насобирал зоопарк:
- отдельный
certbotв cron, который выпускает и продлевает сертификаты Let's Encrypt; - руками прописанные пути к
fullchain.pemиprivkey.pemв каждомserver-блоке; - бойлерплейт на редирект с 80 на 443, на
ssl_protocols, на заголовки; - и классика — забыл перезагрузить nginx после продления серта, словил протухший сертификат, узнал об этом от жены, которая не смогла зайти на семейные заметки.
Каждый новый сервис — это копипаст здоровенного server-блока и правка путей. К десятому разу начинаешь думать, что должен быть способ проще.
Caddyfile, который заменил всё
Способ есть, и он называется Caddy. Весь мой конфиг для двух сервисов выглядит так:
films.example-home.lan {
reverse_proxy localhost:8096
}
notes.example-home.lan {
reverse_proxy localhost:8080
}
Всё. Это не урезанный пример — это реально рабочий минимум. Caddy сам:
- сходит в Let's Encrypt, выпустит сертификат на каждый домен;
- будет молча его продлевать в фоне, без cron и без моего участия;
- поднимет редирект с HTTP на HTTPS;
- выставит вменяемые заголовки безопасности по умолчанию.
Запускаю всё тем же compose, конфиг лежит в /app/caddy/:
services:
caddy:
image: caddy:2
container_name: caddy
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3 (QUIC)
volumes:
- /app/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- /app/caddy/data:/data
- /app/caddy/config:/config
restart: unless-stopped
Обратите внимание на 443:443/udp — это для HTTP/3. Caddy умеет его из коробки, достаточно пробросить UDP-порт, и современные браузеры сами договорятся о QUIC. На спидтестах внутри локалки разницы я особо не заметил, но при доступе снаружи через мобильный интернет страницы админок стали ощутимо живее открываться.
Перезагрузка без даунтайма
Добавил новый сервис — дописал три строчки в Caddyfile и сделал:
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
reload подхватывает изменения на лету, без обрыва текущих соединений. Никакого nginx -t && systemctl reload с замиранием сердца.
Что в итоге
/data я смонтировал в volume не просто так — там лежат выпущенные сертификаты и ACME-аккаунт. Если его потерять, Caddy перевыпустит сертификаты заново, но можно упереться в рейт-лимиты Let's Encrypt. Так что эта папка — то, что обязательно попадает в бэкап.
Конфиг ужался раз в десять, certbot из крона выпилил, про протухшие сертификаты забыл как страшный сон. Единственный минус — экосистема плагинов у nginx всё-таки богаче, и для совсем хитрых сценариев иногда приходится лезть в документацию. Но для домашнего реверс-прокси на десяток сервисов Caddy — это просто счастье. Жалею, что тянул с переездом так долго.