Let's Encrypt cấp chứng chỉ có hạn chín mươi ngày và tự gia hạn chúng, vì thế người ta thôi nghĩ về chúng chỉ một tuần sau khi cấu hình. Rắc rối là việc tự gia hạn hỏng một cách lặng lẽ: không ai thấy lỗi, và ba tháng sau trang web chào đón khách bằng cảnh báo của trình duyệt. Từ năm 2025 Let's Encrypt cũng đã ngừng gửi email thông báo hết hạn, nên lời nhắc từ bên ngoài cuối cùng cũng biến mất.

Dưới đây là các nguyên nhân khiến việc gia hạn ngừng hoạt động, theo thứ tự tần suất giảm dần.

1. Chứng chỉ đã gia hạn còn dịch vụ chưa đọc lại

Phổ biến nhất. certbot renew đã chạy, tệp mới đã nằm trên đĩa, còn nginx hay Apache vẫn giữ tệp cũ trong bộ nhớ — và tiếp tục đưa nó cho khách truy cập cho tới khi cấu hình được nạp lại. Về hình thức thì mọi thứ ổn; trên thực tế trang web có một chứng chỉ đã hết hạn.

Cách chữa là một hook chạy sau khi gia hạn thành công:

sudo certbot renew --deploy-hook "systemctl reload nginx"

Nó được ghi một lần vào tệp gia hạn (/etc/letsencrypt/renewal/example.com.conf, mục [renewalparams], dòng renew_hook) và từ đó tự hoạt động.

2. Máy chủ web thay đổi còn challenge thì không

HTTP-01 challenge đòi hỏi một tệp từ /.well-known/acme-challenge/ phải được phục vụ qua HTTP thuần. Nó thường hỏng như thế này:

  • một chuyển hướng vô điều kiện từ HTTP sang HTTPS được thêm vào cấu hình — challenge đi theo chuyển hướng và thất bại;
  • xuất hiện một quy tắc location ~ /\. với deny all, đóng mọi thư mục có dấu chấm, kể cả .well-known;
  • gốc của trang web chuyển chỗ trong khi cấu hình certbot vẫn giữ --webroot-path cũ;
  • việc chặn theo quốc gia hoặc xác thực cơ bản được bật và nó bắt luôn cả máy chủ xác thực cùng với mọi người.

Thứ tự đúng trong cấu hình: trước hết là một location riêng cho /.well-known/acme-challenge/, rồi mới đến chuyển hướng chung.

3. Timer bị tắt

Việc gia hạn chạy từ một timer systemd hoặc một tác vụ cron, và cả hai đều có thể bị tắt nhầm khi gỡ lỗi hoặc bị mất khi chuyển máy chủ.

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Lệnh thứ hai thực hiện trọn chu trình gia hạn ở chế độ thử mà không tiêu tốn hạn mức của bạn. Đó là phép kiểm tra duy nhất trả lời trước câu hỏi «một tháng nữa nó có gia hạn không» chứ không phải sau khi sự việc đã rồi.

4. Một tên miền không còn trỏ về đây

Chứng chỉ bao phủ năm tên miền, một trong số đó đã chuyển sang host khác, DNS thay đổi. Việc xác thực cho tên miền đó không còn qua được, và certbot không gia hạn toàn bộ chứng chỉ — kể cả bốn tên miền đang hoạt động. Các tên miền thừa phải được gỡ khỏi chứng chỉ, chứ không phải bỏ qua cùng với thông báo.

5. Bạn đụng phải giới hạn

Let's Encrypt giới hạn số chứng chỉ cho mỗi tên miền mỗi tuần. Thông thường đó là kết quả của vòng lặp «không được, thử lại lần nữa» khi gỡ lỗi. Có một máy chủ staging cho các thử nghiệm (--dry-run hoặc --test-cert), và nên dùng nó trước khi hạn mức cạn chứ không phải sau đó.

Hãy kiểm tra thứ được phục vụ, không phải thứ được lưu

Mọi phép kiểm tra dựa trên tệp trên đĩa đều có một khuyết điểm: tệp có thể mới trong khi khách truy cập nhận được chứng chỉ cũ. Hãy nhìn từ phía client:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates -subject -issuer

Tùy chọn -servername là bắt buộc: thiếu nó thì trên máy chủ có vài trang web bạn sẽ nhận chứng chỉ của virtual host đứng đầu tiên chứ không phải cái bạn muốn. Trong kết quả, notAfter là ngày hết hạn thật.

Nhân tiện hãy kiểm tra cả chuỗi:

echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null | grep -c 'BEGIN CERTIFICATE'

Nếu chỉ có một chứng chỉ thì chứng chỉ trung gian không được phục vụ. Trình duyệt thường tha thứ cho cấu hình đó — chúng tự dựng chuỗi — nhưng curl, ứng dụng di động và client Java sẽ không xác thực được. Đây là chuyện kinh điển «bên tôi mở bình thường mà khách hàng lại không dùng được».

Cảnh báo trước bao nhiêu ngày

Ba mươi ngày là cảnh báo đầu tiên hợp lý: đó cũng chính là khoảng thời gian còn lại khi certbot bắt đầu thử gia hạn, nên nếu đến lúc đó chưa có gì xảy ra thì cơ chế đã hỏng. Mười bốn ngày là cảnh báo thứ hai, đã đòi hành động ngay hôm nay. Bảy ngày là tình trạng khẩn cấp.

Điều quan trọng là theo dõi mọi chứng chỉ cùng lúc, kể cả những cái không đến từ Let's Encrypt: những chứng chỉ mua cho cả năm bị quên một cách đáng tin cậy nhất, vì sau một năm ai cũng quên cả việc chúng tồn tại lẫn việc thông báo đi vào hộp thư của ai. Một trang duy nhất với tên miền, ngày tháng và số ngày còn lại khép hẳn câu hỏi này — như ở demo bên dưới.