Caddy: веб-сервер с автоматическим HTTPS за 5 минут

Сайты и веб-серверы
Caddy: веб-сервер с автоматическим HTTPS за 5 минут

Caddy — современный веб-сервер, главная особенность которого — автоматический HTTPS: сертификаты Let's Encrypt выпускаются и продлеваются сами, без certbot, cron-задач и ручной настройки TLS. Конфигурация сайта со статикой или reverse proxy умещается в три строки Caddyfile, а HTTP-запросы сразу перенаправляются на HTTPS. Для небольших проектов на VPS caddy server — самый короткий путь от чистой системы до работающего сайта с валидным сертификатом. Разберём установку Caddy на Ubuntu, синтаксис Caddyfile и типовые сценарии: статика, проксирование и PHP.

Чем Caddy отличается от Nginx и Apache

Caddy написан на Go, распространяется как один бинарный файл и включает встроенный ACME-клиент — тот самый механизм, которому классические веб-серверы требуют внешнюю утилиту вроде certbot (как это делается с Nginx, мы разбирали в статье про SSL-сертификат Let's Encrypt).

ВозможностьCaddyNginx
HTTPS-сертификатАвтоматически, встроенный ACME-клиентОтдельно через certbot
Продление сертификатаАвтоматически, без cronТаймер/cron certbot
Редирект HTTP → HTTPSВключён по умолчаниюНастраивается вручную
HTTP/2Включён по умолчаниюВключается в конфиге
Формат конфигаCaddyfile (минималистичный)Блоки nginx.conf
Экосистема и примерыМеньше готовых рецептовОгромная база знаний

Nginx остаётся стандартом для высоконагруженных проектов и сложных конфигураций — его настройку мы описывали в статье «Установка Nginx на Ubuntu». Caddy же выигрывает там, где важна скорость запуска и минимум обслуживания: личные сайты, пет-проекты, панели, API небольших сервисов.

Что понадобится

  • VPS с Ubuntu 22.04/24.04 (подойдёт и Debian) и root-доступом или sudo;
  • домен с A-записью, указывающей на IP сервера. Без корректной DNS-записи Let's Encrypt не выпустит сертификат — как привязать домен, пошагово описано в статье «Привязка домена к VPS»;
  • открытые порты 80 и 443: они нужны и для работы сайта, и для проверки владения доменом при выпуске сертификата.

Если на сервере уже работает другой веб-сервер, остановите его перед запуском Caddy, иначе порты будут заняты:

sudo systemctl stop nginx 2>/dev/null; sudo systemctl disable nginx 2>/dev/null

Установка Caddy на Ubuntu

Ставим из официального репозитория проекта — так Caddy будет обновляться вместе с системой через apt:

# зависимости для подключения стороннего репозитория
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

# GPG-ключ репозитория Caddy
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 -y caddy

Проверяем, что сервис запустился:

systemctl status caddy
caddy version

Пакет сразу регистрирует systemd-сервис: Caddy запущен, стартует при загрузке системы и уже слушает порт 80. Если открыть IP сервера в браузере, увидите стандартную страницу-заглушку. Осталось открыть порты в файрволе, если используется ufw:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Caddyfile: минимальная конфигурация с HTTPS

Конфигурация лежит в /etc/caddy/Caddyfile. Откройте файл любым редактором:

sudo nano /etc/caddy/Caddyfile

Замените содержимое на минимальный конфиг для статического сайта (подставьте свой домен):

example.com {
    root * /var/www/example.com
    file_server
    encode gzip zstd
}

Построчно:

  • example.com { ... } — блок сайта. Само наличие домена в качестве адреса включает автоматический HTTPS: Caddy выпустит сертификат Let's Encrypt для example.com и настроит редирект с HTTP;
  • root * /var/www/example.com — каталог с файлами сайта;
  • file_server — включает раздачу статических файлов;
  • encode gzip zstd — сжатие ответов.

Создадим каталог и тестовую страницу:

sudo mkdir -p /var/www/example.com
echo '<h1>Caddy works!</h1>' | sudo tee /var/www/example.com/index.html
sudo chown -R caddy:caddy /var/www/example.com

Проверяем синтаксис и применяем конфигурацию без остановки сервера:

caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Через несколько секунд откройте https://example.com — сайт отвечает по HTTPS с валидным сертификатом, а http:// автоматически перенаправляется на https://. Ни одной команды для TLS вы не выполняли: выпуск занял у Caddy считанные секунды, продление тоже пройдёт без вашего участия. О том, как наполнить такой сайт реальным содержимым, — в статье «Статичный сайт на VPS».

Если выпуск не сработал, смотрите журнал — причина почти всегда в DNS или закрытых портах:

journalctl -u caddy --no-pager -n 50

Caddy как reverse proxy

Второй по популярности сценарий — проксирование запросов к приложению на Node.js, Python, Go или к Docker-контейнеру. Вся настройка — одна директива:

app.example.com {
    reverse_proxy 127.0.0.1:3000
}

Caddy принимает HTTPS-запросы, терминирует TLS и передаёт трафик приложению на локальный порт 3000, автоматически подставляя заголовки X-Forwarded-For и X-Forwarded-Proto. Несколько сайтов описываются отдельными блоками в одном Caddyfile:

example.com {
    root * /var/www/example.com
    file_server
}

api.example.com {
    reverse_proxy 127.0.0.1:8080
}

app.example.com {
    reverse_proxy 127.0.0.1:3000
}

Для каждого домена Caddy выпустит собственный сертификат — при условии, что A-записи всех доменов указывают на сервер. Можно распределять нагрузку на несколько бэкендов, просто перечислив их:

api.example.com {
    reverse_proxy 127.0.0.1:8080 127.0.0.1:8081
}

Общая теория проксирования — зачем нужны заголовки и как то же самое делается в Nginx — разобрана в статье «Nginx как reverse proxy».

PHP-сайт на Caddy

Caddy работает с PHP через PHP-FPM. Устанавливаем:

sudo apt install -y php8.3-fpm

Конфигурация сайта с PHP отличается одной директивой php_fastcgi:

example.com {
    root * /var/www/example.com
    php_fastcgi unix//run/php/php8.3-fpm.sock
    file_server
}

Директива сама обрабатывает правила перезаписи в стиле try_files, передачу скриптов в FPM и индексный index.php — то, что в Nginx занимает отдельный блок location. Проверьте версию PHP в системе (php-fpm8.3 -v) и при необходимости поправьте путь к сокету.

Полезные директивы Caddyfile

Несколько часто используемых возможностей:

example.com {
    root * /var/www/example.com
    file_server
    encode gzip zstd

    # свои страницы ошибок
    handle_errors {
        rewrite * /error.html
        file_server
    }

    # заголовки безопасности
    header {
        Strict-Transport-Security "max-age=31536000;"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }

    # логи доступа в файл
    log {
        output file /var/log/caddy/example.com.log
    }

    # редирект с www на основной домен
}

www.example.com {
    redir https://example.com{uri} permanent
}

Все изменения применяются командой sudo systemctl reload caddy — без разрыва текущих соединений. Полный список директив есть в официальной документации Caddy; для большинства сайтов хватает приведённого набора.

Обслуживание и диагностика

Основные команды на каждый день:

# статус и логи
systemctl status caddy
journalctl -u caddy -f

# проверить конфиг перед применением
caddy validate --config /etc/caddy/Caddyfile

# отформатировать Caddyfile по стандарту
caddy fmt --overwrite /etc/caddy/Caddyfile

# применить изменения без даунтайма
sudo systemctl reload caddy

Сертификаты и служебные данные Caddy хранит в /var/lib/caddy/.local/share/caddy — при переносе сервера на другой VPS этот каталог стоит забрать вместе с Caddyfile, тогда повторный выпуск сертификатов не понадобится. Обновляется Caddy обычным sudo apt upgrade, поскольку установлен из репозитория.

Частые вопросы

Нужен ли certbot при использовании Caddy?

Нет, в этом и смысл Caddy: ACME-клиент встроен в сам веб-сервер. Caddy выпускает сертификат Let's Encrypt при первом запуске сайта и продлевает его автоматически задолго до истечения срока. Никаких cron-задач, таймеров и внешних утилит не требуется.

Почему Caddy не выпускает сертификат?

В большинстве случаев причин три: A-запись домена не указывает на IP сервера, порты 80/443 закрыты файрволом или заняты другим веб-сервером. Проверьте DNS командой dig +short example.com, откройте порты в ufw и убедитесь, что Nginx или Apache остановлены. Подробности всегда есть в журнале: journalctl -u caddy -n 50.

Можно ли запустить Caddy на VPS без выделенного IPv4?

Для автоматического выпуска сертификата Let's Encrypt должен достучаться до вашего сервера по портам 80 и 443 — нужен либо выделенный IPv4, либо проброс этих портов на ваш сервер. На NAT VPS с пробросом произвольных портов сайт можно опубликовать на нестандартном порту, но автоматический выпуск сертификата по HTTP-проверке в такой схеме не сработает — потребуется DNS-проверка. Для публичного сайта проще взять обычный VPS с выделенным IP.

Caddy или Nginx — что выбрать?

Caddy — когда нужно быстро поднять сайт или прокси с HTTPS и минимально его обслуживать. Nginx — когда важны тонкая настройка, кеширование, огромная база готовых конфигов и рецептов под любое приложение. Оба сервера надёжны; для типичного проекта на VPS решает не производительность, а то, сколько времени вы готовы тратить на конфигурацию.

Как перенести сайт с Nginx на Caddy?

Остановите Nginx (sudo systemctl disable --now nginx), опишите сайты в /etc/caddy/Caddyfile — блок root + file_server для статики, reverse_proxy вместо proxy_pass, php_fastcgi вместо fastcgi-блоков — и перезапустите Caddy. Сертификаты переносить не нужно: Caddy выпустит свои автоматически. Начните с одного некритичного сайта, убедитесь, что всё работает, затем переносите остальные.


Caddy плюс быстрый VPS — рабочий сайт с HTTPS уже через пять минут после заказа. На Cheap-Host сервер выдаётся за 45–60 секунд: тариф Start за 450 ₽/мес (6 vCPU, 8 ГБ RAM, 96 ГБ NVMe, KVM, Москва) с запасом хватит и для статики, и для нескольких проксируемых приложений. Заказать VPS — на cheap-host.onl.

Читайте также