Caddy — это мощный веб-сервер и обратный прокси-сервер, который автоматически обеспечивает и обновляет HTTPS-сертификаты для ваших доменов, значительно упрощая развертывание защищенных веб-приложений.
Что такое Caddy и зачем он нужен как реверс-прокси?
Caddy — это современный, быстрый и безопасный веб-сервер с открытым исходным кодом, написанный на Go. Его ключевая особенность — автоматическое управление HTTPS-сертификатами с использованием Let's Encrypt или других провайдеров ACME. При использовании в качестве обратного прокси, Caddy перенаправляет входящие запросы от клиентов на один или несколько внутренних бэкенд-серверов, одновременно обеспечивая шифрование трафика и балансировку нагрузки. Это делает его идеальным решением для публикации внутренних сервисов в Интернет с минимальными усилиями по настройке безопасности.
Преимущества Caddy как реверс-прокси:
- Автоматический HTTPS: Caddy автоматически получает, обновляет и управляет SSL/TLS-сертификатами. Это исключает ручную настройку и мониторинг сроков действия сертификатов.
- Простота конфигурации: Использование Caddyfile, простого и интуитивно понятного формата, позволяет быстро настроить даже сложные сценарии проксирования.
- Современные протоколы: Поддержка HTTP/2 и HTTP/3 (QUIC) из коробки.
- Балансировка нагрузки: Встроенные механизмы для распределения запросов между несколькими бэкенд-серверами.
- Легковесность и производительность: Высокая производительность при относительно низком потреблении ресурсов.
- Универсальность: Может быть использован для статического хостинга, API-шлюза, балансировщика нагрузки и других сценариев.
Установка Caddy
Caddy доступен для различных операционных систем. Рекомендуется использовать официальные пакеты или Docker-образ.
Установка в Linux (Debian/Ubuntu)
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
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
sudo apt install caddy
Установка в Docker
docker pull caddy:latest
Для запуска Caddy в Docker с конфигурационным файлом:
docker run -d \
--name caddy \
-p 80:80 \
-p 443:443 \
-v /path/to/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
caddy:latest
Где:
* /path/to/Caddyfile: Путь к вашему конфигурационному файлу Caddyfile на хосте.
* caddy_data: Именованный том для хранения сертификатов и других данных Caddy.
Базовая конфигурация реверс-прокси
Конфигурация Caddy осуществляется через Caddyfile. Это текстовый файл, который определяет поведение сервера.
Пример: Проксирование одного сервиса
Предположим, у вас есть веб-приложение, работающее на localhost:8080, и вы хотите сделать его доступным по доменному имени yourdomain.com с автоматическим HTTPS.
Создайте файл Caddyfile со следующим содержимым:
yourdomain.com {
reverse_proxy localhost:8080
}
Сохраните файл и запустите Caddy. Если вы используете systemd, Caddy автоматически найдет Caddyfile в /etc/caddy/Caddyfile.
sudo systemctl enable caddy
sudo systemctl start caddy
Как это работает:
1. Caddy перехватывает запросы для yourdomain.com.
2. Автоматически запрашивает и устанавливает SSL/TLS-сертификат для yourdomain.com через Let's Encrypt.
3. Весь HTTP-трафик на yourdomain.com автоматически перенаправляется на HTTPS.
4. Запросы, пришедшие по HTTPS, проксируются на внутренний сервер localhost:8080.
Проксирование нескольких доменов
app.yourdomain.com {
reverse_proxy localhost:8081
}
api.yourdomain.com {
reverse_proxy localhost:8082
}
В этом примере Caddy будет обслуживать два разных поддомена, каждый из которых проксируется на свой внутренний порт, и для каждого будет автоматически настроен HTTPS.
Продвинутые возможности реверс-прокси
Caddy предоставляет множество опций для тонкой настройки проксирования.
Балансировка нагрузки
Для распределения запросов между несколькими бэкенд-серверами.
yourdomain.com {
reverse_proxy 192.168.1.10:8080 192.168.1.11:8080 192.168.1.12:8080 {
# Стратегия балансировки нагрузки (по умолчанию round_robin)
lb_policy least_conn
}
}
Доступные политики балансировки нагрузки (lb_policy):
* random: Случайный выбор бэкенда.
* round_robin (по умолчанию): Последовательный выбор бэкенда.
* least_conn: Выбор бэкенда с наименьшим количеством активных соединений.
* ip_hash: Выбор бэкенда на основе хеша IP-адреса клиента, обеспечивая "липкость" сессии.
Передача заголовков (Headers)
Важно передавать оригинальные заголовки запроса бэкенд-серверу, чтобы он мог корректно идентифицировать клиента и протокол. Caddy делает это автоматически для большинства стандартных заголовков (Host, X-Forwarded-For, X-Forwarded-Proto, X-Real-IP). Однако, при необходимости, их можно настроить явно.
yourdomain.com {
reverse_proxy localhost:8080 {
# Явная передача заголовков (обычно не требуется, так как Caddy делает это по умолчанию)
header_up Host {http.request.host}
header_up X-Real-IP {remote_ip}
header_up X-Forwarded-For {remote_ip}
header_up X-Forwarded-Proto {http.request.scheme}
header_up X-Forwarded-SSL on
}
}
WebSockets
Caddy автоматически поддерживает проксирование WebSockets без дополнительной настройки.
yourdomain.com {
reverse_proxy localhost:8080
}
Запросы с заголовками Upgrade: websocket и Connection: upgrade будут корректно проксированы.
Маршрутизация по пути (Path Matching)
Можно проксировать разные пути на разные бэкенды.
yourdomain.com {
handle /api/* {
reverse_proxy localhost:8081
}
handle /app/* {
reverse_proxy localhost:8082
}
# Все остальные запросы
handle {
reverse_proxy localhost:8080
}
}
Директива handle позволяет группировать правила для определенных путей.
Аутентификация (Basic Auth)
Для защиты сервиса базовой HTTP-аутентификацией.
yourdomain.com {
basicauth / {
username JDJhJDE0JGl3R3p0T1J6bFp1a1pMNEt2a21vYk8uU21Ld1l6Q3R3RjB2V3U2d0l0Z25zT0x3S0JqM0t1
}
reverse_proxy localhost:8080
}
Пароль должен быть хеширован. Для генерации хеша используйте команду caddy hash-password.
caddy hash-password --plaintext yourpassword
Перенаправления (Redirects)
Перенаправление старых URL на новые или принудительное использование HTTPS для определенных путей (хотя Caddy делает это автоматически для всего сайта).
yourdomain.com {
redir /old-path /new-path 301
# Принудительное HTTPS для всех запросов (обычно не требуется, Caddy делает это по умолчанию)
# redir http://yourdomain.com https://yourdomain.com{uri}
reverse_proxy localhost:8080
}
Проксирование на UNIX-сокеты
Для приложений, использующих UNIX-сокеты вместо TCP-портов (например, Gunicorn, uWSGI).
yourdomain.com {
reverse_proxy unix//var/run/app.sock
}
CORS (Cross-Origin Resource Sharing)
Добавление заголовков CORS для взаимодействия с фронтендом на другом домене.
api.yourdomain.com {
header Access-Control-Allow-Origin "*"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "Content-Type, Authorization"
header Access-Control-Max-Age "86400"
# Для обработки OPTIONS-запросов
handle_options {
respond 204
}
reverse_proxy localhost:8081
}
Управление сертификатами и Let's Encrypt
Caddy по умолчанию использует ACME (Automatic Certificate Management Environment) для автоматического получения сертификатов.
ACME HTTP Challenge
Это стандартный метод, при котором Caddy создает временный файл на порту 80 вашего сервера. Let's Encrypt обращается к этому файлу для проверки владения доменом. Это работает, если порт 80 доступен из Интернета.
ACME TLS-ALPN Challenge
Caddy слушает на порту 443 и использует специальный протокол TLS-ALPN для проверки владения доменом. Это работает, даже если порт 80 заблокирован.
ACME DNS Challenge
Используется для получения wildcard-сертификатов (*.yourdomain.com) или в сценариях, где сервер не имеет прямого доступа из Интернета (например, во внутренних сетях). Для этого Caddy должен иметь возможность управлять DNS-записями вашего домена (например, через API Cloudflare, Route 53 и т.д.).
*.yourdomain.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
reverse_proxy localhost:8080
}
В этом примере Caddy использует токен API Cloudflare (переданный через переменную окружения CLOUDFLARE_API_TOKEN) для создания временной TXT-записи в DNS, подтверждающей владение доменом.
On-Demand TLS
Позволяет Caddy запрашивать сертификаты только тогда, когда на домен приходит первый запрос. Полезно для динамических сред с большим количеством поддоменов.
:443 { # Слушаем на порту 443 для всех входящих HTTPS-запросов
tls {
on_demand
}
# Используйте placeholder для имени хоста
reverse_proxy {http.request.host}:8080
}
Для on_demand необходимо настроить лимиты, чтобы предотвратить злоупотребления:
{
email your_email@example.com
acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} # Если используете DNS challenge
on_demand_tls {
ask http://localhost:8080/check_domain # Endpoint для проверки домена
burst 100
interval 5m
}
}
# В остальной части Caddyfile
# ...
ask — это URL, который Caddy будет проверять, чтобы убедиться, что домен существует и ему разрешено выдавать сертификат.
Мониторинг и логирование
Caddy предоставляет возможности для логирования доступа и ошибок.
Логи доступа
yourdomain.com {
log {
output file /var/log/caddy/access.log {
roll_size 10mb
roll_keep 5
}
format json
}
reverse_proxy localhost:8080
}
output file: Указывает путь к файлу логов.roll_size,roll_keep: Настройка ротации логов.format: Формат логов (по умолчаниюcommon_log, можноjson).
Логи ошибок
Логи ошибок Caddy по умолчанию выводятся в stderr. Для систем systemd это означает, что они будут доступны через journalctl.
journalctl -u caddy -f
Сравнение с Nginx
| Характеристика | Caddy | Nginx |
|---|---|---|
| Автоматический HTTPS | Встроенный, полностью автоматический с Let's Encrypt (ACME). | Требует ручной настройки или интеграции с Certbot. |
| Конфигурация | Caddyfile: простой, декларативный, легко читаемый. | Nginx.conf: мощный, но синтаксис более сложный и многословный. |
| HTTP/3 (QUIC) | Поддержка из коробки. | Требует компиляции из исходников с дополнительными модулями. |
| WebSockets | Автоматическая поддержка. | Требует явной настройки proxy_set_header и proxy_read_timeout. |
| Балансировка нагрузки | Встроена, простая конфигурация. | Мощные возможности, но требует более детальной настройки. |
| Перезагрузка конфига | Мягкая перезагрузка без разрыва соединений. | Мягкая перезагрузка без разрыва соединений. |
| Расширяемость | Модульная архитектура, плагины на Go. | Модули на C/C++ или Lua. |
| Целевая аудитория | Разработчики, малые и средние проекты, быстрые развертывания. | Крупные проекты, высокая производительность, сложные инфраструктуры. |
| Лицензия | Apache 2.0 | BSD-подобная. |
Caddy является отличным выбором для тех, кто ищет простоту, автоматизацию HTTPS и современные протоколы без необходимости глубокого погружения в сложную конфигурацию. Nginx остается стандартом для высоконагруженных систем, где требуется максимальный контроль и тонкая оптимизация.
Примеры реальных сценариев
Проксирование нескольких Docker-контейнеров
Предположим, у вас есть два Docker-контейнера: webapp (порт 80) и api (порт 80), и вы хотите сделать их доступными через Caddy.
# Caddyfile
app.yourdomain.com {
reverse_proxy webapp:80
}
api.yourdomain.com {
reverse_proxy api:80
}
Пример docker-compose.yml:
version: '3.8'
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- internal_network
webapp:
image: your_webapp_image:latest
restart: unless-stopped
networks:
- internal_network
api:
image: your_api_image:latest
restart: unless-stopped
networks:
- internal_network
volumes:
caddy_data:
caddy_config:
networks:
internal_network:
driver: bridge
В этом случае Caddy и бэкенды находятся в одной Docker-сети (internal_network) и могут обращаться друг к другу по именам сервисов (webapp, api).
Защита внутренних сервисов с помощью Caddy
Используйте Caddy для предоставления безопасного доступа к внутренним инструментам, таким как Grafana, Prometheus, Portainer и т.д.
grafana.yourdomain.com {
basicauth / {
username JDJhJDE0JGl3R3p0T1J6bFp1a1pMNEt2a21vYk8uU21Ld1l6Q3R3RjB2V3U2d0l0Z25zT0x3S0JqM0t1
}
reverse_proxy localhost:3000 # Порт Grafana
}
prometheus.yourdomain.com {
reverse_proxy localhost:9090 # Порт Prometheus
}
Caddy автоматически обеспечит HTTPS для grafana.yourdomain.com и prometheus.yourdomain.com, а также добавит базовую аутентификацию для Grafana, защищая ваши внутренние инструменты от несанкционированного доступа.