Caddy: один бинарник вместо nginx + certbot

Сертификат кончился ровно в ночь перед релизом. Сайт лежит, certbot молчит, cron-хук сломался ещё два обновления назад — и ты в три часа ночи лезешь в консоль разбираться, какое именно звено зоопарка отвалилось на этот раз.
Так у меня выглядела жизнь на связке nginx + certbot + cron: три сущности, которые надо кормить, обновлять и чинить, и одна и та же драма каждые 90 дней. В какой-то момент я сформулировал требование предельно просто:
Я устал бояться даты экспирации. Хочу включить и забыть.
Что такое Caddy и почему «один бинарник»
Caddy — современный веб-сервер и обратный прокси, который из коробки умеет авто-HTTPS. Без внешних скриптов и плясок вокруг хуков.
- Дистрибутив — один бинарник.
- Никаких зависимостей из репозитория.
- Конфиг — читаемый Caddyfile.
Это и есть главное отличие от привычной схемы: вместо нескольких пакетов и скриптов, которые надо синхронно поддерживать, у тебя один исполняемый файл и один конфиг.

Авто-HTTPS: как Caddy сам выпускает и продлевает сертификаты
Caddy поднимает сайт на HTTPS сразу: сам получает и продлевает сертификаты Let's Encrypt через HTTP-01 или TLS-ALPN челлендж, сам их хранит и обновляет. Никаких моих скриптов, никаких cron-хуков, которые тихо ломаются при очередном апдейте.
Главное — чтобы домен указывал на ваш сервер и порты 80/443 были доступны снаружи (у меня — через NAT на роутере). Дальше всё работает само.
Простой Caddyfile
Ниже — базовый сайт на своём домене и проксирование поддоменов во внутреннюю сеть 198.51.100.0/24. Третий блок заодно показывает простейший ACL: наружу пускаем только офисный адрес, остальным — 403.
example.ru {
encode gzip
handle_path /health { respond 200 "ok" }
}
# Поддомен с прокси на сервис во внутренней сети
monitor.example.ru {
reverse_proxy 198.51.100.14:3001
}
# Базовый ACL (ограничим доступ по IP)
internal.example.ru {
@from_office remote_ip 203.0.113.250
handle @from_office {
reverse_proxy 198.51.100.16:8000
}
handle {
respond 403 "forbidden"
}
}
Это весь конфиг: домен, поддомены, прокси и правило доступа — без отдельных файлов под сертификаты и без служебных location-блоков для валидации.

Сравнение с «nginx + certbot + cron»
- Конфиги: читаемый Caddyfile против разнесённых блоков nginx.
- HTTPS: авто-выпуск и продление внутри Caddy против внешних хуков certbot.
- Обновления: один бинарник против нескольких пакетов и скриптов.
- Ошибки: меньше движущихся частей — меньше мест, где можно выстрелить себе в ногу.
- Логи и метрики: встроенные JSON-логи, экспорт в любимый стэк.
Грабли и как их обойти
Переезд не бесплатный — пара мест, где легко споткнуться, всё же есть.
- Реверс-прокси за NAT: пробросьте 80/443 на Caddy, тогда HTTP-01 пройдёт. Если 80-й занят — используйте TLS-ALPN на 443.
- Проверка валидации: убедитесь, что запрос на проверку домена реально доходит до Caddy (особенно если трафик идёт через туннель на роутер), иначе выпуск сертификата молча упадёт.
- Адреса в правилах доступа: в ACL держите только диапазоны-заглушки — 203.0.113.x для WAN и офиса, 198.51.100.x для сервисов, 10.0.x для LAN. Реальные адреса в конфигах и статьях не светим.
Итог
Переключение на Caddy убрало зоопарк и ежеквартальные драмы с продлениями: один бинарник, авто-HTTPS, простой конфиг. Мораль простая — не вешай прод на cron-хуки и собственную память. Если софт умеет сам выпускать и продлевать сертификаты, пусть это делает софт, а не ты ночью в консоли.
Полезное:
- Caddy — https://caddyserver.com/
- Документация — https://caddyserver.com/docs/