Зачем вообще смотреть в сторону Caddy
Caddy Server обычно всплывает в одном и том же сценарии: вы поднимаете сайт или приложение, хотите HTTPS «без боли», а дальше внезапно оказывается, что инфраструктура состоит не из одного виртуального хоста, а из набора сервисов (PHP, Node.js, Python, админки, API, статика). В мире Nginx это решается проверенными конфигами, но за них нужно отвечать: сертификаты, обновления, редиректы, заголовки, SNI, OCSP, перезагрузки и так далее.
Сильная сторона Caddy в том, что он из коробки делает то, что в Nginx часто собирается руками: Auto HTTPS (получение и продление сертификатов по ACME), корректные редиректы HTTP→HTTPS и дружелюбный формат конфигурации (Caddyfile), который проще читать и сопровождать.
Но Caddy — не «Nginx, только проще». Это другой продукт с собственными решениями по логированию, обработке заголовков, перезапуску и хранению состояния (сертификаты, аккаунт ACME). Ниже — практично: как работает Auto HTTPS, как поднять reverse proxy, что учесть при миграции и где чаще всего ошибаются.
Как устроен Auto HTTPS в Caddy (и где тут ACME)
В типовой конфигурации Caddy вы указываете домен, а сервер сам:
- слушает 80/443 (или нужные вам порты);
- поднимает TLS;
- получает сертификат у ACME CA (часто Let’s Encrypt) и продлевает его заранее;
- делает редирект с HTTP на HTTPS (если нет причин оставлять HTTP);
- хранит приватные ключи и метаданные в собственном storage.
Важно понимать: Auto HTTPS — это не «магия», а набор автоматизаций вокруг ACME-челленджей. Для публичного домена чаще всего используется HTTP-01 (проверка через порт 80). Если порт 80 недоступен извне, придётся переключаться на DNS-01 (через DNS API) или менять архитектуру.
Практическое правило: если вы хотите, чтобы Caddy «сам сделал HTTPS», обеспечьте доступность входящего 80/tcp и корректные A/AAAA-записи на IP сервера. Дальше всё упирается в DNS и фаервол.
Хранилище сертификатов и «состояние» Caddy
В отличие от подхода «certbot выписал файлы в /etc/letsencrypt», Caddy ведёт собственное хранилище. Это влияет на эксплуатацию:
- Бэкапы: убедитесь, что каталог данных Caddy попадает в резервные копии.
- Кластеры/несколько инстансов: два Caddy за одним доменом без общего storage могут упереться в ACME-лимиты или гонки обновления. В таких сценариях нужен общий storage или единая точка терминации TLS.
- Миграции: перенося сервис на новый сервер, можно перенести и storage Caddy, чтобы не выпускать сертификаты заново.
Caddyfile на практике: минимальный рабочий конфиг
Ключевое преимущество Caddyfile — декларативность. Самый простой сайт с обратным прокси до приложения (например, Node.js на 127.0.0.1:3000) выглядит так:
example.com {
reverse_proxy 127.0.0.1:3000
}
Этого достаточно, чтобы Caddy поднял HTTPS и проксировал запросы.
Несколько доменов и поддоменов
Обычно вы быстро приходите к конфигу, где на одном сервере живут несколько сайтов:
site-one.example.com {
reverse_proxy 127.0.0.1:3001
}
site-two.example.com {
reverse_proxy 127.0.0.1:3002
}
Caddy сам запросит сертификаты на каждый hostname (если DNS указывает на сервер и порт 80 доступен).
Статика + прокси: типовой «фронт + API»
Частый паттерн: раздаём статику (SPA) и проксируем API:
example.com {
root * /var/www/app
file_server
handle_path /api/* {
reverse_proxy 127.0.0.1:8080
}
}
Здесь важно именно handle_path: он «съедает» префикс пути (/api) перед проксированием, что удобно для бэкенда.

Если вы планируете держать несколько доменов/сервисов и управлять портами под ACME и reverse proxy без ограничений, обычно удобнее разворачивать Caddy на VDS.
Чем Caddy отличается от Nginx в эксплуатации
Если смотреть на Caddy как на альтернативу Nginx, полезно сравнить не только синтаксис, но и ежедневную «операционку»: релизы, диагностику, перезагрузки, поведение по умолчанию.
Перезагрузка и проверка конфигурации
В Nginx вы делаете тест (nginx -t) и reload. В Caddy обычно мыслите категориями «валидировать» и «загрузить конфигурацию», после чего обязательно смотрите логи момента применения, потому что ошибки ACME/TLS проявляются именно там.
Если держите конфиги в Git и деплоите через CI/CD, имеет смысл выделить шаг в пайплайне, который хотя бы проверяет синтаксис (и отдельно прогоняет smoke-тесты по критичным URL после перезагрузки).
Логи и диагностика: что смотреть в первую очередь
Caddy достаточно разговорчив в части TLS/ACME. Это плюс: когда сертификат не выпускается, лог — главный источник правды. Типовые причины:
- порт 80 недоступен извне (фаервол, security group, NAT, проброс портов);
- DNS A/AAAA указывает не туда;
- у домена включён прокси/CDN, который мешает HTTP-01 челленджу;
- упёрлись в rate limits ACME (часто при пересоздании инстанса без переноса storage).
Если у вас нужен wildcard или порт 80 принципиально закрыт, заранее планируйте DNS-01. В этом случае полезно держать под рукой понятный процесс автоматизации и восстановления. По теме можно опереться на материал DNS-01 для wildcard-сертификатов: автоматизация и типовые ошибки.
HTTPS «по умолчанию» и последствия
В Nginx можно годами держать «просто HTTP» и потом вручную добавлять TLS, редиректы и HSTS. Caddy, наоборот, подталкивает к HTTPS как к дефолту. Это обычно удобно, но требует осознанности в особых случаях:
- внутренние сервисы без публичного DNS;
- локальные домены (например,
.local), где публичный ACME не сработает; - нестандартные порты и сложные схемы проброса.
Практика reverse proxy: заголовки, WebSocket, таймауты
Когда вы ставите Caddy как фронтенд, почти всегда важны три вещи: корректные заголовки, поддержка WebSocket и таймауты. Хорошая новость — базовый reverse proxy в Caddy уже достаточно «правильный» для большинства приложений, включая WebSocket. Но для продакшена часто нужно чуть больше контроля.
Явно задаём заголовки (когда бэкенд ожидает конкретику)
Бэкенды и middleware любят X-Forwarded-Proto, X-Forwarded-For, Host. Caddy обычно проставляет нужное сам, но при миграции со сложного Nginx-конфига стоит проверить ожидания приложения. Пример явной настройки:
example.com {
reverse_proxy 127.0.0.1:3000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Если перед Caddy стоит ещё один прокси или балансер, отдельно продумайте trust-модель: какие источники вы считаете доверенными и какие forwarded-заголовки принимаете. Иначе можно случайно начать доверять поддельным заголовкам от клиента.
Таймауты и «долго думающие» запросы
В Nginx часто вручную крутят proxy_read_timeout под длинные операции. В Caddy таймауты тоже настраиваются, но подход зависит от схемы проксирования и требований приложения. Практика: сначала измерьте реальные требования (API, загрузки, стриминг), затем зафиксируйте таймауты на уровне прокси и приложения, и обязательно проверьте поведение при обрыве клиента.
Миграция с Nginx на Caddy: чек-лист без сюрпризов
Миграция чаще ломается не на «как написать reverse_proxy», а на деталях вокруг: редиректы, заголовки безопасности, ограничения и исключения.
1) Редиректы и каноникал (www/non-www, http/https)
В Caddy редирект HTTP→HTTPS обычно автоматический. Но редирект между www и «голым» доменом нужно явно описывать, если у вас есть канонический вариант. Пример: отправляем www на основной домен:
www.example.com {
redir https://example.com{uri} permanent
}
example.com {
reverse_proxy 127.0.0.1:3000
}
2) Статика, кеширование и заголовки
Nginx часто используют как «машину раздачи статики». Caddy тоже умеет, но механика отличается. Проверьте:
- как выставляются
Cache-ControlиETag; - не было ли в Nginx тонких правил для
*.css,*.js,*.woff2; - нужна ли компрессия (gzip/brotli) и где она включается;
- не полагались ли вы на специфичные правила
try_filesдля SPA.
3) Ограничения на тело запроса (загрузки)
Если пользователи загружают файлы, в Nginx почти всегда есть лимиты вроде client_max_body_size. В Caddy аналогичные ограничения настраиваются иначе. При переносе обязательно тестируйте реальные загрузки (и по размеру, и по времени), иначе получите внезапные 413/502 уже в продакшене.
4) Доверие к прокси-цепочке и реальные IP
Если перед вашим сервером стоит внешний балансер, CDN или защита, убедитесь, что логика «реального IP» корректна. Ошибки здесь приводят к двум классам проблем:
- в логах всегда один IP (адрес балансера), ломается аналитика и rate-limit на уровне приложения;
- хуже: доверяем клиентским
X-Forwarded-Forи получаем spoofing IP в логах и ACL.

ACME: типовые ошибки и как быстро понять, что не так
Раз в запросах часто фигурирует ACME, отдельно проговорим, что чаще всего ломает выпуск сертификата и как это быстро отдиагностировать.
Порт 80 закрыт или занят
Для HTTP-01 Caddy должен принимать входящие на 80/tcp. Если порт занят (например, старый Nginx ещё слушает 80), Caddy не пройдёт проверку. Решения: освободить порт, временно выключить конкурирующий сервис или перейти на DNS-01.
DNS указывает не на тот IP (или есть «лишний» AAAA)
Классика: A-запись указывает правильно, а AAAA указывает на старый IPv6 или IPv6-маршрут не настроен. ACME-проверка может пойти по IPv6 и упасть. Практика: либо чините IPv6 до конца, либо убирайте AAAA, пока не готовы.
Если домен ещё настраивается, часто удобнее держать регистрацию и DNS в одном месте: проще управлять A/AAAA и быстрее переезжать между серверами. По ситуации может пригодиться регистрация доменов и централизованное управление DNS-записями.
Слишком частые попытки и лимиты CA
Если вы много раз пересоздаёте Caddy и не переносите его storage, вы быстро набьёте лимиты на выпуск. Это особенно заметно в контейнерах при деплоях «с нуля». Лечение простое: сохраняйте данные Caddy на постоянном диске и не выпускайте сертификаты заново без причины. Для понимания механики лимитов полезно почитать материал лимиты Let’s Encrypt: SAN, rate limits и стратегия автоматизации.
Если домены у вас постоянно добавляются (проекты, окружения, поддомены), заранее закладывайте нормальный процесс учёта и продления: это экономит время на миграциях и дебаге ACME.
Когда Caddy — отличный выбор, а когда лучше остаться на Nginx
Caddy хорошо заходит, если:
- вы хотите максимально быстро получить корректный HTTPS без отдельного certbot и cron;
- у вас много небольших сервисов и важна простота конфигов;
- вы часто поднимаете новые домены и поддомены и не хотите «рутинить» TLS;
- вы предпочитаете инфраструктуру, где безопасные дефолты включены сразу.
Лучше подумать дважды, если:
- у вас крайне кастомный Nginx-конфиг (сложные map, нестандартные фазы обработки, специфичные модули);
- TLS терминируется не на веб-сервере, а выше (L7-балансер), и Auto HTTPS почти не даёт выигрыша;
- вы строите многосерверную схему и не готовы сразу продумать общий storage и координацию сертификатов;
- ваша команда уже отточила Nginx до автоматизма и важнее предсказуемость, чем скорость старта.
Мини-шпаргалка: быстрый старт и проверка
Для тестового запуска обычно достаточно установить Caddy, прописать домен в Caddyfile и убедиться, что DNS и порты готовы. Базовый набор проверок перед тем, как объявлять «у нас всё на Caddy»:
- проверить доступность 80/443 извне;
- проверить A и AAAA записи и реальную маршрутизацию;
- пройтись по критичным URL: логин, загрузки, API, WebSocket;
- проверить заголовки и корректность
X-Forwarded-Proto(иначе возможны бесконечные редиректы в приложении); - зафиксировать, где лежит storage Caddy и как он бэкапится.
Итоги
Caddy Server действительно можно рассматривать как альтернативу Nginx в типовых задачах: сайты, API, проксирование на приложения и автоматизация TLS. Его сильная сторона — Auto HTTPS на базе ACME и понятный Caddyfile, который упрощает жизнь, когда доменов и сервисов становится много.
При этом Caddy лучше воспринимать не как «упрощённый Nginx», а как отдельный подход: он берёт на себя TLS-операционку, но взамен требует аккуратности с портами, DNS и хранением состояния. Если учесть эти моменты заранее, переход на reverse proxy Caddy часто оказывается не рискованной миграцией, а приятным упрощением инфраструктуры.


