Cách cài đặt máy chủ web Caddy với HTTPS tự động
Cài Caddy trên Ubuntu từ kho chính thức, viết Caddyfile cho site tĩnh và reverse proxy, hiểu chứng chỉ tự động, systemd, nhật ký, và lỗi thường gặp khi chuyển từ Nginx.

Caddy là máy chủ web lấy và gia hạn chứng chỉ TLS theo mặc định. Với VPS nhỏ host một hoặc hai tên miền, điều đó bỏ cả một lớp timer Certbot và tệp snippet Nginx. Ngôn ngữ cấu hình (Caddyfile) ngắn. Reverse proxy, gzip và HTTP/2 là tính năng bình thường, không phải cuối tuần mô-đun thêm.
Nginx vẫn là lựa chọn đúng với một số shop: bạn đã có cấu hình đã chiến đấu, hoặc cần mô-đun rất cụ thể. Hướng dẫn này dành cho trường hợp phổ biến kia — bạn muốn HTTPS chạy trên VPS Hiddence mới mà không thuộc include snippet. Chúng ta sẽ cài Caddy từ kho apt chính thức, giải thích nó nói chuyện với Let's Encrypt thế nào, phục vụ site tĩnh, proxy ứng dụng cục bộ, host nhiều tên miền, xem nhật ký, và xử lý các cuộc tranh cổng 80 với Apache hoặc Nginx cũ.
Khi nào Caddy phù hợp
HTTPS tự động là tiêu đề, nhưng thắng hàng ngày là ít bộ phận chuyển động hơn. Caddy lắng nghe 80 và 443, chuyển HTTP sang HTTPS, và lưu chứng chỉ trong thư mục dữ liệu. Bạn vẫn cần tên miền trỏ tới VPS. Bạn vẫn cần không phá ACME (tường lửa 80/tcp, không tiến trình khác cướp :80). Chứng chỉ wildcard cần mô-đun nhà cung cấp DNS — đó là đường dài hơn chứng chỉ một host.
- HTTP→HTTPS tự động và gia hạn chứng chỉ
- Caddyfile dễ đọc thay vì khối server dài
- Reverse proxy đủ sức cho Node, Python, PHP-FPM qua cấu hình thêm, hoặc backend Docker
- HTTP/2 và mặc định TLS hiện đại không cần bảng cipher
- Đơn vị systemd từ gói chính thức
Yêu cầu
Tên miền phải phân giải tới VPS này trước khi Caddy chứng minh ACME HTTP-01. Nếu DNS còn lan truyền, Caddy sẽ thất bại cấp và thử lại; trông như 'Caddy hỏng' khi chỉ là DNS. Dừng Apache hoặc Nginx trước nếu chúng chiếm 80/443.
- Ubuntu 22.04 hoặc 24.04
- Bản ghi A của tên miền tới IP VPS (và AAAA nếu dùng IPv6)
- Cổng 80 và 443 trống và được cho phép trên tường lửa
- Root hoặc sudo
Bước 1: Cài Caddy từ kho chính thức
Đừng cài Caddy cũ ngẫu nhiên từ Ubuntu universe mặc định nếu muốn hành vi TLS và ACME hiện tại. Dự án Caddy ghi nguồn apt. Sau cài, người dùng caddy tồn tại và dịch vụ được bật.
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-pagerBước 2: Caddyfile đầu tiên — site tĩnh
Caddyfile mặc định là /etc/caddy/Caddyfile. Thay bằng tên miền của bạn. Caddy sẽ cố lấy chứng chỉ ngay khi cấu hình tải nếu hostname không phải localhost. Đặt tệp site trong thư mục người dùng caddy đọc được (thường quyền kiểu www-data, nhưng gói dùng người dùng caddy).
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 -fBước 3: Reverse proxy ứng dụng cục bộ
Nếu Gunicorn, Node hoặc Docker lắng nghe 127.0.0.1:8000, Caddy nên là tiến trình công cộng duy nhất. Chỉ thị reverse_proxy chuyển Host và X-Forwarded-* theo cách hợp lý với hầu hết ứng dụng. Nếu ứng dụng sinh URL HTTP tuyệt đối, đặt cờ proxy tin cậy / HTTPS trong ứng dụng (Django SECURE_PROXY_SSL_HEADER, Express trust proxy, v.v.).
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
# }Bước 4: Tường lửa và systemd
Cho phép 80 và 443. Đơn vị của Caddy là caddy.service; reload đủ sau khi sửa Caddyfile nếu tiến trình khỏe. Nếu đổi biến môi trường cho plugin DNS, khởi động lại đầy đủ rõ hơn. Chứng chỉ nằm dưới /var/lib/caddy/.local/share/caddy/ theo mặc định — gồm đường đó trong bản sao lưu nếu bạn quan tâm giới hạn tốc độ khi cài lại.
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/Bước 5: Nhật ký, nén và header
Nhật ký truy cập giúp khi bot đập một đường dẫn hoặc khi bạn gỡ 404. Có thể ghi theo site. Thêm header bảo mật nếu bạn host ứng dụng trình duyệt; đừng copy gói header khổng lồ mà không hiểu HSTS (một khi đặt max-age dài, trình duyệt nhớ).
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 caddyBước 6: PHP và phần thêm khác
Caddy có thể nói chuyện với PHP-FPM bằng chỉ thị php_fastcgi. Đủ cho nhiều host WordPress hoặc Laravel, nhưng bạn vẫn cần php-fpm đã cài và đường socket khớp. Nếu đã có cấu hình Nginx PHP hoàn hảo, chuyển trong một tối là tùy chọn — Caddy tỏa sáng hơn ở reverse proxy + tĩnh + TLS tự động.
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-fpmChuyển từ Nginx không bất ngờ downtime
Dừng Nginx trước khi chạy Caddy nếu không chúng tranh 80/443. Hạ TTL DNS hôm trước nếu bạn cũng chuyển IP. Thử bằng curl --resolve để đánh VPS mới trước khi đổi bản ghi A. Giữ cấu hình Nginx trong git một tuần phòng rollback.
- systemctl stop nginx && systemctl disable nginx
- Cài Caddy, xác thực Caddyfile, chạy Caddy
- curl -I --resolve example.com:443:NEW_IP https://example.com
- Chỉ rồi mới đổi DNS nếu IP mới
- Cấp lại là tự động; đừng cũng chạy Certbot với cùng hostname
Khắc phục sự cố
Thất bại ACME gần như luôn là DNS, tường lửa, hoặc dịch vụ khác trên cổng 80. Dòng nhật ký Caddy nhắc tls.obtain. Nếu site chạy HTTP nhưng không HTTPS, việc cấp chưa hoàn tất. Nếu thấy quá nhiều chứng chỉ, bạn đụng giới hạn tốc độ Let's Encrypt — dùng CA staging khi thử, không production.
- validate thất bại: cú pháp Caddyfile, thiếu ngoặc
- permission denied trên root: chown caddy cho thư mục site
- bind: address already in use — ss -tulpn | grep -E ':80|:443'
- hết thời gian chứng chỉ: dig +short tên miền từ VPS, ufw allow 80
- 502 reverse_proxy: backend chết, hoặc bạn proxy tới localhost từ mạng container sai
Ghi chú bảo mật
Mặc định TLS của Caddy thận trọng. Việc của bạn là bảo mật ứng dụng và SSH. Đừng bật API quản trị Caddy trên giao diện công cộng. Endpoint quản trị mặc định là cục bộ; để vậy. Nếu dùng Caddyfile từ internet, đọc mọi matcher — snippet reverse_proxy /* tới IP nội bộ có thể thành proxy mở.
- Không lộ API quản trị
- Giữ gói cập nhật
- HSTS chỉ sau khi chắc HTTPS chạy cho mọi hostname
- Tách hostname thử và production để bảo vệ giới hạn tốc độ ACME
Mẹo
- caddy fmt --overwrite /etc/caddy/Caddyfile giữ tệp dễ đọc
- Dùng snippet import khi có nhiều site tương tự
- Với Docker, image caddy:alpine với Caddyfile gắn là phổ biến
- Chứng chỉ wildcard cần mô-đun DNS và token API — bảo vệ token đó
- Đọc journalctl -u caddy trước khi viết lại cả tệp
Caddy trên VPS là: gói chính thức, Caddyfile ngắn, cổng 80/443 mở, DNS đã trỏ máy chủ, và systemd reload sau khi sửa. Dùng như máy chủ tệp tĩnh hoặc reverse proxy trước Gunicorn, Node, hoặc Docker. HTTPS tự động chạy khi ACME trả lời được trên cổng 80; nếu cấp thất bại, sửa DNS và xung đột cổng trước khi đổ lỗi Caddy. Sao lưu /var/lib/caddy nếu bạn hay cài lại.