Назад до блогу
Серпень 19, 2026Посібники

Як встановити вебсервер Caddy з автоматичним HTTPS

Встановлення Caddy на Ubuntu з офіційного репозиторію, Caddyfile для статики й зворотного проксі, автоматичні сертифікати, systemd, логи й типові помилки під час переходу з Nginx.

Як встановити вебсервер Caddy з автоматичним HTTPS

Caddy — вебсервер, який за замовчуванням сам отримує й продовжує сертифікати TLS. Для невеликого VPS з одним-двома доменами це прибирає цілий шар таймерів Certbot і фрагментів Nginx. Мова конфігурації (Caddyfile) коротка. Зворотний проксі, gzip і HTTP/2 — звичайні можливості, а не вихідні з модулями.

Nginx і далі доречний, якщо конфіги вже обкатані або потрібен рідкісний модуль. Цей гайд — про інший частий випадок: HTTPS на свіжому VPS Hiddence без заучування include. Поставимо Caddy з офіційного apt, розберемо, як він говорить із Let's Encrypt, віддамо статику, проксуємо локальний застосунок, повісимо кілька доменів, подивимося логи й типову бійку за порт 80 з Apache або старим Nginx.

Коли Caddy добре заходить

Автоматичний HTTPS — заголовок, а в побуті виграш у меншій кількості рухомих частин. Caddy слухає 80 і 443, переводить HTTP на HTTPS і зберігає сертифікати у своєму каталозі даних. Домен на VPS усе одно потрібен. ACME все одно можна зламати (закритий 80/tcp, чужий процес на :80). Wildcard-сертифікат потребує модуля DNS-провайдера — це довше, ніж сертифікат на один хост.

  • Самі HTTP→HTTPS і продовження сертифіката
  • Читабельний Caddyfile замість довгих блоків server
  • Зворотний проксі для Node, Python, PHP-FPM (з додатковим налаштуванням) або контейнерів Docker
  • HTTP/2 і нормальні налаштування TLS без таблиці шифрів
  • Готовий unit systemd з офіційного пакета

Що потрібно

Домен має резолвитися на цей VPS до того, як Caddy доведе ACME HTTP-01. Поки DNS роз’їжджається, випуск падає й повторюється — здається, що «Caddy зламаний», хоча винен лише DNS. Apache або Nginx зупиніть, якщо вони тримають 80/443.

  • Ubuntu 22.04 або 24.04
  • A-запис домену на IP VPS (і AAAA, якщо використовуєте IPv6)
  • Порти 80 і 443 вільні й дозволені в брандмауері
  • Root або sudo

Крок 1. Встановлення з офіційного репозиторію

Не беріть випадково старий Caddy з universe Ubuntu, якщо потрібні актуальні TLS і ACME. У проєкту Caddy є apt-джерело. Після встановлення з’являється користувач caddy, служба вмикається.

bash
ssh root@YOUR_VPS_IP
apt update && apt -y install debian-keyring debian-archive-keyring apt-transport-https curl gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list

apt update
apt -y install caddy

caddy version
systemctl status caddy --no-pager

Крок 2. Перший Caddyfile — статичний сайт

Файл за замовчуванням — /etc/caddy/Caddyfile. Підставте свій домен. Caddy спробує взяти сертифікат одразу після завантаження конфігу, якщо ім’я не localhost. Файли сайту покладіть у каталог, який може читати користувач caddy.

bash
mkdir -p /var/www/example
echo '<h1>It works</h1>' > /var/www/example/index.html
chown -R caddy:caddy /var/www/example

cat >/etc/caddy/Caddyfile <<'EOF'
example.com {
    root * /var/www/example
    file_server
    encode gzip
}
EOF

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

# Watch issuance:
journalctl -u caddy -f

Крок 3. Зворотний проксі до локального застосунку

Якщо Gunicorn, Node або Docker слухають 127.0.0.1:8000, Caddy має бути єдиним публічним процесом. Директива reverse_proxy нормально передає Host і X-Forwarded-* для більшості застосунків. Якщо застосунок генерує абсолютні HTTP-посилання, увімкніть довіру до проксі в самому застосунку (SECURE_PROXY_SSL_HEADER у Django, trust proxy в Express тощо).

bash
app.example.com {
    encode gzip
    reverse_proxy 127.0.0.1:8000
}

# Several hosts in one file are normal:
# blog.example.com {
#     root * /var/www/blog
#     file_server
# }

Крок 4. Брандмауер і systemd

Дозвольте 80 і 443. Служба — caddy.service; після правок Caddyfile достатньо reload, якщо процес живий. Якщо змінюєте змінні для DNS-плагіна, зрозуміліший повний restart. Сертифікати за замовчуванням лежать під /var/lib/caddy/.local/share/caddy/ — цей шлях варто копіювати, якщо часто перевстановлюєте систему й не хочете впиратися в ліміти Let's Encrypt.

bash
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

systemctl enable --now caddy
systemctl reload caddy

# Backup cert storage (path may vary slightly by version):
ls -la /var/lib/caddy/

Крок 5. Логи, стиснення й заголовки

Журнал доступу допомагає, коли бот долбить шлях або ви ловите 404. Логи можна ввімкнути на сайт. Заголовки безпеки для браузерного застосунку додавайте осмислено: довгий HSTS браузери запам’ятовують.

bash
example.com {
    root * /var/www/example
    file_server
    encode gzip
    log {
        output file /var/log/caddy/example.log
    }
    header {
        X-Content-Type-Options nosniff
        Referrer-Policy no-referrer-when-downgrade
        -Server
    }
}

mkdir -p /var/log/caddy
chown caddy:caddy /var/log/caddy
systemctl reload caddy

Крок 6. PHP та інші доповнення

Caddy вміє php_fastcgi до PHP-FPM. Для частини WordPress і Laravel цього вистачає, але FPM усе одно потрібно поставити й указати правильний сокет. Якщо у вас уже ідеальний PHP-конфіг Nginx, переїжджати за один вечір не обов’язково — Caddy сильніший на зв’язці «статика + проксі + автоматичний TLS».

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

# Confirm FPM is running:
systemctl status php8.3-fpm

Переїзд з Nginx без сюрпризів

Зупиніть Nginx до запуску Caddy, інакше вони б’ються за 80/443. За день до зміни IP зменшіть TTL DNS. Перевіряйте curl --resolve, щоб бити в новий VPS до зміни A-запису. Конфіги Nginx потримайте в git тиждень на випадок відкату.

  • systemctl stop nginx && systemctl disable nginx
  • Поставте Caddy, перевірте Caddyfile, запустіть службу
  • curl -I --resolve example.com:443:NEW_IP https://example.com
  • Лише потім міняйте DNS, якщо IP новий
  • Випуск сертифіката автоматичний; Certbot на той самий хост паралельно не ганяйте

Якщо щось не працює

Збої ACME майже завжди DNS, брандмауер або чужа служба на 80. У логах Caddy це tls.obtain. Сайт відкривається по HTTP, але не по HTTPS — випуск не завершився. Забагато сертифікатів — ліміт Let's Encrypt; на тестах використовуйте staging CA, не бойовий.

  • validate не проходить: синтаксис Caddyfile, пропущена дужка
  • permission denied на root: chown caddy для каталогу сайту
  • bind: address already in use — ss -tulpn | grep -E ':80|:443'
  • Таймаут сертифіката: dig +short домену з VPS, ufw allow 80
  • 502 у reverse_proxy: бекенд мертвий або localhost указаний не з тієї мережі (контейнери)

Зауваження щодо захисту

Налаштування TLS у Caddy помірні. Ваша зона — застосунок і SSH. Адмін-API Caddy на публічний інтерфейс не виставляйте: за замовчуванням він локальний, так і залиште. Caddyfile з інтернету читайте цілком: фрагмент, який проксує /* на внутрішній IP, може стати відкритим проксі.

  • Адмін-API зовні не відкривати
  • Пакет оновлювати
  • HSTS — лише коли HTTPS точно працює на всіх іменах
  • Тестові й бойові імена розведіть, щоб не спалити ліміт ACME

Поради

  • caddy fmt --overwrite /etc/caddy/Caddyfile робить файл читабельним
  • import-фрагменти, коли сайтів багато і вони схожі
  • У Docker часто образ caddy:alpine і примонтований Caddyfile
  • Wildcard потрібен DNS-модуль і токен API — токен бережіть
  • Спочатку journalctl -u caddy, потім переписування всього файла

Caddy на VPS — офіційний пакет, короткий Caddyfile, відкриті 80/443, DNS уже дивиться на сервер, reload systemd після правок. Статика або зворотний проксі перед Gunicorn, Node чи Docker. Автоматичний HTTPS працює, коли ACME відповідає на порту 80; якщо випуск падає, лагодьте DNS і конфлікт портів, а не «сам Caddy». Каталог /var/lib/caddy копіюйте, якщо часто перевстановлюєте систему.