✅ Good
Caddy¶
Caddy — сучасний веб-сервер, який автоматично налаштовує HTTPS через Let's Encrypt. В UMTC ми використовуємо Caddy як основний реверс-проксі для всіх публічних сервісів.
Чому Caddy?
- **Автоматичний HTTPS** — не треба вручну налаштовувати сертифікати
- **Простий синтаксис** — Caddyfile читається як документація
- **Швидкий перезапуск** — zero-downtime reload
- **Все з коробки** — gzip, headers, logging вже вбудовані
Архітектура¶
flowchart TB
subgraph internet["Інтернет"]
CLIENT[👤 Клієнти]
end
subgraph caddy["Caddy :443"]
TLS["🔐 TLS Termination<br/>Let's Encrypt"]
ROUTER["🔀 Routing<br/>по домену/шляху"]
end
subgraph backends["Бекенди"]
WIKI["📚 Wiki<br/>:3000"]
API["⚙️ API<br/>:8000"]
MATRIX["💬 Matrix<br/>:8008"]
STATIC["📁 Static<br/>/var/www"]
end
CLIENT -->|HTTPS| TLS
TLS --> ROUTER
ROUTER -->|wiki.example.com| WIKI
ROUTER -->|wiki.example.com/api| API
ROUTER -->|matrix.example.com| MATRIX
ROUTER -->|static.example.com| STATIC
style caddy fill:#22c55e,color:#000
style backends fill:#dbeafeВстановлення¶
Ubuntu/Debian¶
# Додаємо репозиторій
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
# Перевіряємо
caddy version
Docker¶
services:
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
volumes:
caddy_data:
caddy_config:
Caddyfile — конфігурація¶
Файл конфігурації знаходиться в /etc/caddy/Caddyfile.
Базовий reverse proxy¶
wiki.example.com {
reverse_proxy localhost:3000
}
Це все! Caddy автоматично:
- Отримає сертифікат Let's Encrypt
- Налаштує редірект HTTP → HTTPS
- Почне проксювати запити на порт 3000
Кілька бекендів¶
flowchart LR
REQ["wiki.example.com/api/users"]
CADDY["Caddy"]
API["Backend :8000"]
FRONT["Frontend :3000"]
REQ --> CADDY
CADDY -->|"/api/*"| API
CADDY -->|"/*"| FRONT
style CADDY fill:#22c55e,color:#000wiki.example.com {
# API запити → backend
handle /api/* {
reverse_proxy localhost:8000
}
# Все інше → frontend
handle {
reverse_proxy localhost:3000
}
}
Порядок важливий
Директиви `handle` обробляються в порядку від специфічних до загальних. Спочатку `/api/*`, потім все інше.
Статичні файли¶
static.example.com {
root * /var/www/static
file_server
}
Кілька доменів¶
wiki.example.com {
reverse_proxy localhost:3000
}
api.example.com {
reverse_proxy localhost:8000
}
matrix.example.com {
reverse_proxy localhost:8008
}
Автоматичний HTTPS¶
Caddy автоматично отримує та оновлює сертифікати Let's Encrypt.
Вимоги¶
| Вимога | Перевірка |
|---|---|
| Домен направлений на сервер | dig wiki.example.com |
| Порт 80 відкритий | Потрібен для ACME challenge |
| Порт 443 відкритий | Для HTTPS трафіку |
Перевірка сертифікатів¶
# Список сертифікатів
caddy list-certs
# Примусове оновлення (якщо потрібно)
sudo systemctl reload caddy
Staging сертифікати
Для тестування використовуйте staging сервер Let's Encrypt, щоб не вичерпати ліміти:
{
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
Корисні директиви¶
Security headers¶
(security) {
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
-Server
}
}
wiki.example.com {
import security
reverse_proxy localhost:3000
}
Gzip стиснення¶
wiki.example.com {
encode gzip zstd
reverse_proxy localhost:3000
}
Логування¶
wiki.example.com {
log {
output file /var/log/caddy/wiki.log {
roll_size 10mb
roll_keep 5
}
format json
}
reverse_proxy localhost:3000
}
Basic Auth¶
# Генеруємо хеш пароля
caddy hash-password
# Enter password: ****
# $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
admin.example.com {
basicauth {
admin $2a$14$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
reverse_proxy localhost:8080
}
Заголовки для бекенду¶
wiki.example.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Команди управління¶
# Статус сервісу
sudo systemctl status caddy
# Перезавантаження конфігурації (без downtime!)
sudo systemctl reload caddy
# Повний перезапуск
sudo systemctl restart caddy
# Перевірка синтаксису Caddyfile
caddy validate --config /etc/caddy/Caddyfile
# Форматування Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile
# Логи в реальному часі
sudo journalctl -u caddy -f
Повний приклад для UMTC Wiki¶
# Глобальні налаштування
{
email admin@eliah.one
}
# Загальні директиви
(common) {
encode gzip
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
-Server
}
}
# Wiki
wiki.eliah.one {
import common
# API
handle /api/* {
reverse_proxy backend:8000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
# Frontend
handle {
reverse_proxy frontend:3000
}
log {
output file /var/log/caddy/wiki.log
format json
}
}
# Auth (Keycloak/Authentik)
auth.eliah.one {
import common
reverse_proxy authentik:9000
}
# Matrix
matrix.eliah.one {
import common
reverse_proxy synapse:8008
}
Troubleshooting¶
| Проблема | Причина | Рішення |
|---|---|---|
| 502 Bad Gateway | Бекенд не запущений | docker ps, перевірте сервіс |
| SSL помилка | Домен не направлений | Перевірте DNS A-запис |
| Не оновлюється конфіг | Синтаксична помилка | caddy validate |
| Повільний сайт | Немає стиснення | Додайте encode gzip |
Діагностика¶
# Перевірка з'єднання з бекендом
curl -v localhost:3000
# Перевірка DNS
dig wiki.example.com
# Перевірка сертифіката
openssl s_client -connect wiki.example.com:443 -servername wiki.example.com
# Перегляд логів помилок
sudo journalctl -u caddy -p err
Пов'язані теми¶
- Проксі та реверс-проксі — теорія
- Docker — контейнеризація
- Налаштування Caddy — покрокова інструкція
- TLS/SSL — криптографічні протоколи
Шлях: services/web/caddy.md