1. Зачем Caddy — в чём разница с Nginx
Nginx — мощный и гибкий, но его конфигурация многословна. Даже простой сайт с HTTPS требует нескольких блоков, отдельной установки Certbot и ручной настройки обновления сертификатов. Caddy решает ту же задачу кардинально проще.
Сравним один и тот же случай: опубликовать сайт на домене с HTTPS.
1. Установить Nginx
2. Установить Certbot
3. Написать конфиг сайта (~25 строк)
4. Запустить certbot --nginx -d домен
5. Настроить cron для обновления
≈ 15 минут + шанс ошибиться
1. Установить Caddy
2. Написать Caddyfile (3 строки)
3. Перезапустить Caddy
SSL — автоматически
Обновление — автоматически
≈ 3 минуты
| Возможность | Nginx | Caddy |
|---|---|---|
| SSL-сертификаты | Certbot вручную, cron обновление | Автоматически от Let's Encrypt |
| HTTP → HTTPS редирект | Отдельный server-блок | Встроено, по умолчанию |
| HTTP/2 и HTTP/3 | Нужно включать вручную | Работает из коробки |
| Сжатие (gzip) | Настраивать вручную | Директива encode в одну строку |
| Конфиг статического сайта | ~25 строк | 3 строки |
| Конфиг reverse proxy | ~20 строк | 1 строка |
| Производительность | Очень высокая | Высокая (немного уступает Nginx) |
| Порог вхождения | Средний | Низкий |
Когда лучше выбрать Nginx
Nginx остаётся лучшим выбором при очень высоких нагрузках (тысячи запросов в секунду), необходимости тонкой настройки буферов и кэширования, или если вы уже глубоко знаете Nginx и конфигурация вас не пугает. Caddy — для тех, кто хочет результат быстро и без лишней сложности.
2. Установка на Ubuntu
Caddy не входит в стандартные репозитории Ubuntu, но у него есть официальный apt-репозиторий от разработчиков. Устанавливаем оттуда — так будут приходить обновления через обычный apt upgrade.
Шаг 1: добавить репозиторий и установить
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
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После установки Caddy автоматически запускается как systemd-сервис и начинает слушать порты 80 и 443. Проверяем что всё в порядке:
systemctl status caddyДолжно быть Active: active (running). Если порты 80/443 заняты Nginx — сначала остановите его:
sudo systemctl stop nginx
sudo systemctl disable nginxШаг 2: открыть порты в файрволле
Если на сервере включён UFW — разрешаем HTTP и HTTPS:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcpКлючевые файлы и директории
| Путь | Что это |
|---|---|
| /etc/caddy/Caddyfile | Главный конфиг — здесь описываем сайты |
| /var/www/html/ | Дефолтная директория для файлов сайта |
| /var/lib/caddy/ | Данные Caddy: SSL-сертификаты, ключи |
| /var/log/caddy/ | Логи доступа и ошибок |
3. Статический сайт с HTTPS
Начнём с самого простого случая: опубликовать папку с HTML-файлами по домену. Сначала убедитесь что A-запись вашего домена уже указывает на IP сервера — Caddy проверяет это при выдаче сертификата.
Создаём директорию с сайтом
sudo mkdir -p /var/www/mysite
echo '<h1>Привет! Caddy работает.</h1>' | sudo tee /var/www/mysite/index.htmlРедактируем Caddyfile
Открываем главный конфиг и добавляем наш сайт. Замените example.com на ваш реальный домен:
example.com {
root * /var/www/mysite
file_server
}Это весь конфиг. Caddy сам:
- ✓Получит SSL-сертификат от Let's Encrypt
- ✓Настроит автоматическое обновление сертификата
- ✓Сделает редирект HTTP → HTTPS
- ✓Включит HTTP/2
Применяем конфиг
sudo systemctl reload caddyЧерез 10–20 секунд сайт откроется по https://example.com с зелёным замком.
Добавить сжатие и заголовки безопасности
Caddy поддерживает gzip/zstd-сжатие через директиву encode. Одна строка — и браузеры будут получать сжатый контент:
example.com {
root * /var/www/mysite
encode zstd gzip
file_server
}Про asterisk в root *
Звёздочка в root * /var/www/mysite означает “применить ко всем запросам”. Это называется matcher — фильтр запросов. Можно указать root /api/* /var/www/api, чтобы задать корень только для путей, начинающихся с /api/.
4. Reverse proxy — одна строка
Reverse proxy (обратный прокси) нужен когда у вас есть приложение — Node.js, Python, Go — которое запускается на локальном порту (например, 3000), и вы хотите открыть его по домену с HTTPS. Caddy принимает запросы снаружи и передаёт их приложению.
Предположим, приложение запущено на порту 3000:
app.example.com {
reverse_proxy localhost:3000
}Всё. Caddy выдаст SSL, настроит HTTPS и будет проксировать запросы на порт 3000. Сравните с аналогичным конфигом для Nginx — там 20+ строк.
Типичные приложения и их порты
| Приложение | Дефолтный порт | reverse_proxy |
|---|---|---|
| Next.js | 3000 | localhost:3000 |
| FastAPI / Flask | 8000 | localhost:8000 |
| Node.js Express | 3000 | localhost:3000 |
| Django | 8000 | localhost:8000 |
| Grafana | 3000 | localhost:3000 |
| Vaultwarden | 80 | localhost:80 |
| Gitea | 3000 | localhost:3000 |
| n8n | 5678 | localhost:5678 |
Передача реального IP клиента
Если приложение должно видеть реальный IP посетителя (а не 127.0.0.1 от Caddy) — добавьте заголовки. Большинство фреймворков умеют читать X-Forwarded-For:
app.example.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}5. Несколько сайтов в одном конфиге
На одном VPS часто нужно запустить несколько сайтов или приложений — каждое на своём домене. В Caddy это просто: добавляете новый блок в Caddyfile, и каждый домен автоматически получает свой SSL-сертификат.
# Сайт 1: статика
mysite.ru {
root * /var/www/mysite
encode zstd gzip
file_server
}
# Сайт 2: Node.js-приложение
app.mysite.ru {
reverse_proxy localhost:3000
}
# Сайт 3: Python/FastAPI
api.mysite.ru {
reverse_proxy localhost:8000
}
# Сайт 4: Grafana
monitor.mysite.ru {
reverse_proxy localhost:3001
}
# Редирект с www на основной домен
www.mysite.ru {
redir https://mysite.ru{uri} permanent
}Применяем изменения:
# Сначала проверяем конфиг на ошибки
sudo caddy validate --config /etc/caddy/Caddyfile
# Если ошибок нет — применяем
sudo systemctl reload caddyCaddy запросит сертификаты для всех новых доменов параллельно. Через 20–30 секунд все сайты будут доступны по HTTPS.
PHP-сайт (WordPress и др.)
Для PHP-сайтов нужен php-fpm. Устанавливаем и настраиваем:
sudo apt install php8.2-fpm php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring php8.2-xmlmyblog.ru {
root * /var/www/myblog
encode zstd gzip
# PHP-файлы передаём на обработку php-fpm
php_fastcgi unix//run/php/php8.2-fpm.sock
# Остальные файлы отдаём напрямую
file_server
}Для WordPress
WordPress требует чтобы все несуществующие пути перенаправлялись на index.php. Хорошая новость: директива php_fastcgi в Caddy делает это автоматически — WordPress работает без дополнительных настроек.
6. SPA (React, Vue, Next.js)
Single-Page Application (SPA) — это приложения на React, Vue или Svelte, где маршрутизация работает в браузере через JavaScript. Если пользователь откроет myapp.ru/profile напрямую, сервер попытается найти файл /profile и вернёт 404. Нужно всегда отдавать index.html — JS-роутер сам разберётся куда вести.
React/Vue/Svelte (статическая сборка)
После npm run build кладём папку dist в /var/www/myapp:
myapp.ru {
root * /var/www/myapp/dist
encode zstd gzip
# Если файл не найден — отдаём index.html
# Это нужно для React Router, Vue Router и т.д.
try_files {path} /index.html
file_server
}Next.js (серверный режим)
Next.js в серверном режиме (SSR/SSG с node server) запускается как отдельный процесс на порту 3000. Caddy работает как reverse proxy перед ним:
myapp.ru {
reverse_proxy localhost:3000
}SPA + API на одном домене
Часто фронтенд и бэкенд живут на одном домене: фронт по пути /, API по пути /api/. Caddy отлично справляется с таким роутингом:
myapp.ru {
# Запросы к /api/* уходят на бэкенд (порт 8000)
handle /api/* {
reverse_proxy localhost:8000
}
# Всё остальное — React SPA
handle {
root * /var/www/myapp/dist
try_files {path} /index.html
file_server
}
}7. Управление и диагностика
Основные команды
| Команда | Что делает |
|---|---|
| sudo systemctl reload caddy | Применить изменения конфига без прерывания работы (graceful) |
| sudo systemctl restart caddy | Полный перезапуск (кратковременный downtime) |
| sudo systemctl status caddy | Статус сервиса и последние строки лога |
| sudo caddy validate --config /etc/caddy/Caddyfile | Проверить синтаксис конфига на ошибки |
| sudo journalctl -u caddy -f | Следить за логами в реальном времени |
| sudo journalctl -u caddy --since "5 min ago" | Логи за последние 5 минут |
Как проверить что сертификат получен
Запускаем Caddy и смотрим логи — при первом старте с новым доменом увидим процесс получения сертификата:
sudo journalctl -u caddy -fУспешное получение сертификата выглядит так:
INFO tls.obtain acquiring lock {"identifier": "example.com"}
INFO tls.obtain successfully obtained certificate {"identifier": "example.com"}
INFO autosaved config {"file": "/var/lib/caddy/.config/caddy/autosave.json"}Локальная разработка без домена
При использовании localhost вместо домена Caddy автоматически создаёт самоподписанный сертификат. Let's Encrypt при этом не используется:
localhost:8080 {
reverse_proxy localhost:3000
}Рабочий процесс при изменении конфига
- Редактируем
/etc/caddy/Caddyfile - Проверяем синтаксис:
sudo caddy validate --config /etc/caddy/Caddyfile - Применяем:
sudo systemctl reload caddy - Проверяем что нет ошибок:
sudo systemctl status caddy