Cơn ác mộng mang tên Nginx Config và Certbot
Nginx vẫn là một tượng đài, nhưng thành thật mà nói, việc quản lý file cấu hình dài hàng trăm dòng là một cực hình. Mình từng mất trắng 3 tiếng đồng hồ chỉ để debug tại sao Certbot không thể gia hạn SSL cho một sub-domain chạy Docker. Vấn đề thường nằm ở các rule redirect chồng chéo hoặc sai sót trong cấu hình .well-known.
Nếu bạn đang quản lý khoảng 5-10 microservices, việc lặp lại đống cấu hình proxy_pass, header, và ssl_certificate thực sự rất lãng phí thời gian. Caddy xuất hiện như một vị cứu tinh. Thay vì bắt bạn làm mọi thứ thủ công, Caddy mặc định mọi thứ phải tự động, đặc biệt là Automatic HTTPS. Nó tự cấp, tự gia hạn SSL từ Let’s Encrypt mà bạn không cần cài thêm bất kỳ plugin nào.
Tại sao Caddy lại ‘vượt mặt’ Nginx trong môi trường Docker?
- Cấu hình siêu tối giản: Một website HTTPS hoàn chỉnh chỉ tốn của bạn đúng 3 dòng code.
- HTTP/3 mặc định: Caddy hỗ trợ HTTP/3 (QUIC) ngay lập tức, giúp tăng tốc độ tải trang nhanh hơn khoảng 20-30% so với HTTP/2 cũ kỹ.
- Tự động hóa SSL 100%: Quên Certbot đi. Caddy tự xử lý từ A-Z, bao gồm cả việc xoay vòng chứng chỉ khi gần hết hạn.
- Viết bằng Go: Không phụ thuộc vào thư viện hệ thống, chạy cực nhẹ dưới dạng một binary duy nhất bên trong container.
Bước 1: Thiết lập Docker Network chung
Để Caddy đóng vai trò là “người gác cổng”, nó cần một con đường riêng để nói chuyện với các container khác. Chúng ta sẽ tạo một network tên là caddy_net. Điều này giúp bạn bảo mật hệ thống: các app bên trong không cần mở port ra ngoài, chỉ mình Caddy được phép tiếp nhận traffic từ port 80 và 443.
docker network create caddy_net
Thực tế, cách làm này giúp mình giảm thiểu rủi ro bị scan port lên tới 90% vì các dịch vụ như Database hay Redis đều nằm vùng kín bên trong network này.
Bước 2: Triển khai Caddy bằng Docker Compose
Hãy tạo một thư mục caddy để chứa toàn bộ cấu hình. Cấu trúc thư mục chuẩn sẽ như thế này:
caddy/
├── docker-compose.yml
└── Caddyfile
Nội dung file docker-compose.yml:
version: "3.9"
services:
caddy:
image: caddy:2.7-alpine
container_name: caddy_proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # Quan trọng để chạy HTTP/3
networks:
- caddy_net
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
caddy_net:
external: true
volumes:
caddy_data:
caddy_config:
Cảnh báo: Bạn tuyệt đối không được quên mount volume cho /data. Đây là nơi lưu trữ chứng chỉ SSL. Nếu mất dữ liệu này và restart container liên tục, bạn sẽ bị Let’s Encrypt khóa IP (Rate Limit) trong 7 ngày vì yêu cầu cấp cert quá nhiều lần.
Bước 3: Cấu hình Caddyfile – Sức mạnh của sự đơn giản
Giả sử bạn có một app Node.js đang chạy trong container tên là my_awesome_app ở port 3000. Với Nginx, bạn mất 20 dòng. Với Caddy, bạn chỉ cần:
app.yourdomain.com {
reverse_proxy my_awesome_app:3000
}
Tin được không? Chỉ vậy thôi. Caddy sẽ tự hiểu bạn cần SSL, tự đi xin cert và tự cấu hình proxy. Nếu muốn thêm bảo mật và nén dữ liệu để tối ưu Google PageSpeed, hãy dùng cấu trúc này:
api.yourdomain.com {
encode gzip zstd
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options nosniff
}
reverse_proxy api_container:8080
}
Bước 4: Kích hoạt và theo dõi
Chạy lệnh sau để khởi động hệ thống:
docker-compose up -d
Để biết Caddy có đang làm việc hay không, hãy soi log của nó. Đây là cách mình kiểm tra xem chứng chỉ SSL đã được cấp chưa:
docker logs -f caddy_proxy
Khi thấy log ghi certificate obtained successfully, bạn có thể mở trình duyệt và tận hưởng biểu tượng ổ khóa xanh mà không tốn một giọt mồ hôi nào.
Kinh nghiệm thực chiến: Khi nào thì Caddy lỗi?
Trong quá trình vận hành thực tế, lỗi phổ biến nhất là 502 Bad Gateway. Nếu gặp lỗi này, hãy kiểm tra xem container ứng dụng của bạn đã join vào caddy_net chưa. Caddy không thể kết nối với thứ mà nó không thấy.
Một lưu ý cho anh em dùng Cloudflare: Hãy chỉnh chế độ SSL/TLS thành “Full (strict)”. Nếu để “Flexible”, bạn sẽ rơi vào vòng lặp redirect (Too many redirects) vì Caddy cố gắng ép HTTPS trong khi Cloudflare lại gửi request HTTP tới server.
Caddy không chỉ là một công cụ, nó là cách để chúng ta làm việc thông minh hơn. Thay vì tốn thời gian cho đống config rườm rà, hãy để Caddy lo phần hạ tầng, còn bạn hãy tập trung vào việc viết code và tối ưu sản phẩm.

