Website được thiết kế tối ưu cho thành viên chính thức. Hãy Đăng nhập hoặc Đăng ký để truy cập đầy đủ nội dung và chức năng. Nội dung bạn cần không thấy trên website, có thể do bạn chưa đăng nhập. Nếu là thành viên của website, bạn cũng có thể yêu cầu trong nhóm Zalo "CNTT" các nội dung bạn quan tâm.

Bài 11. Cấu hình HTTPS với Certbot (Let’s Encrypt)

ICT

1. Vai trò của Certbot trong chiến lược HTTPS

Trong chiến lược HTTPS đã xác định ở Bài 10, toàn bộ chứng chỉ SSL được:

  • Quản lý tập trung tại Reverse Proxy,

  • Không phân tán xuống các backend,

  • Gia hạn tự động, hạn chế tối đa thao tác thủ công.

Để hiện thực hóa chiến lược này, Certbot (Let’s Encrypt) là công cụ phù hợp nhất vì:

  • Miễn phí,

  • Được hỗ trợ rộng rãi,

  • Tích hợp tốt với Nginx,

  • Có khả năng tự động gia hạn.

Tuy nhiên, khi số lượng domain lớn, Certbot phải được triển khai có chiến lược, không dùng theo kiểu “cài nhanh – chạy thử”.


2. Nguyên tắc triển khai Certbot trong hệ thống này

Trước khi cấu hình, cần thống nhất các nguyên tắc sau:

  1. Chỉ cài Certbot trên Reverse Proxy

  2. Mỗi domain có server block rõ ràng trước khi xin chứng chỉ

  3. Không để Certbot tự động chỉnh sửa cấu hình một cách không kiểm soát

  4. Gia hạn hoàn toàn tự động

  5. Có khả năng mở rộng cho hàng trăm domain

Tài liệu này không sử dụng chế độ Certbot “tự động sửa toàn bộ cấu hình Nginx” để tránh:

  • Cấu hình bị thay đổi khó kiểm soát,

  • Phá vỡ cấu trúc folder/snippets đã chuẩn hóa.


3. Cài đặt Certbot trên Debian 12

3.1. Cập nhật hệ thống

 
apt update
apt upgrade -y

3.2. Cài Certbot và plugin Nginx

 
apt install -y certbot python3-certbot-nginx

Kiểm tra phiên bản:

 
certbot --version

4. Chuẩn bị Nginx trước khi xin chứng chỉ

4.1. Điều kiện bắt buộc

Trước khi chạy Certbot:

  • Domain phải trỏ DNS về IP Reverse Proxy (192.168.1.88 NAT ra Internet).

  • Nginx đã chạy HTTP (port 80) cho domain đó.

  • Có server block HTTP hợp lệ.


4.2. Ví dụ server block HTTP chuẩn

server {
   listen 80;
   server_name qlcl.example.com;
   location / {
       proxy_pass http://10.10.10.66;
       include snippets/proxy/proxy-common.conf;
   }
}

Kiểm tra:

nginx -t
systemctl reload nginx

5. Xin chứng chỉ HTTPS cho một domain

5.1. Chạy Certbot ở chế độ kiểm soát

certbot --nginx -d qlcl.example.com

Certbot sẽ:

  • Xác thực domain bằng HTTP-01 challenge,

  • Tạo chứng chỉ tại:

    /etc/letsencrypt/live/qlcl.example.com/ 
  • Đề nghị redirect HTTP → HTTPS (có thể chọn hoặc từ chối).

Khuyến nghị:
Không để Certbot tự động chỉnh sửa redirect, mà tự cấu hình redirect trong Nginx theo chuẩn hệ thống.


6. Cấu trúc file chứng chỉ Let’s Encrypt

Sau khi thành công:

/etc/letsencrypt/live/qlcl.example.com/
├── cert.pem
├── chain.pem
├── fullchain.pem
└── privkey.pem

Trong Nginx, chỉ sử dụng:

  • fullchain.pem

  • privkey.pem


7. Cấu hình HTTPS server block chuẩn

7.1. Ví dụ server block HTTPS cho web app

server {
   listen 443 ssl;
   server_name qlcl.example.com;
   ssl_certificate     /etc/letsencrypt/live/qlcl.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/qlcl.example.com/privkey.pem;
   include snippets/ssl/ssl-common.conf;
   include snippets/ssl/ssl-params.conf;
   include snippets/headers/security-headers.conf;
   include snippets/proxy/proxy-common.conf;
   include snippets/proxy/proxy-webapp.conf;
   location / {
       proxy_pass http://10.10.10.66;
   }
}

7.2. Redirect HTTP → HTTPS (tự kiểm soát)

 
server {
   listen 80;
   server_name qlcl.example.com;
   return 301 https://$host$request_uri;
}

8. Xin chứng chỉ cho nhiều domain

8.1. Xin nhiều domain trong một lệnh

 
certbot --nginx \
 -d benhviena.vn \
 -d www.benhviena.vn

8.2. Chứng chỉ riêng cho từng domain (khuyến nghị)

  • Dễ quản lý.

  • Dễ thu hồi hoặc debug.

  • Không ảnh hưởng domain khác khi lỗi.


9. Gia hạn chứng chỉ tự động

9.1. Cơ chế gia hạn mặc định

Certbot cài sẵn systemd timer:

systemctl list-timers | grep certbot

Gia hạn chạy:

  • 2 lần/ngày

  • Chỉ gia hạn khi còn < 30 ngày


9.2. Test gia hạn (bắt buộc)

certbot renew --dry-run

Nếu không lỗi → hệ thống sẵn sàng production.


10. Reload Nginx sau khi gia hạn

Certbot mặc định reload Nginx.
Có thể kiểm soát bằng hook:

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

11. Quản lý hàng trăm domain: lưu ý quan trọng

  1. Không xóa tay thư mục /etc/letsencrypt

  2. Không copy chứng chỉ giữa các server

  3. Backup /etc/letsencrypt định kỳ

  4. Theo dõi log gia hạn

Log:

/var/log/letsencrypt/letsencrypt.log 

12. Những lỗi thường gặp và cách tránh

12.1. Certbot không xác thực được domain

  • DNS chưa trỏ đúng.

  • Port 80 chưa mở hoặc bị firewall chặn.

12.2. Certbot sửa cấu hình Nginx ngoài ý muốn

  • Luôn review file .conf sau khi chạy.

  • Ưu tiên cấu hình thủ công server block HTTPS.


13. Mối liên hệ với failover backend (QMS ↔ AI)

Vì HTTPS terminate tại Reverse Proxy:

  • Đổi backend IP không ảnh hưởng SSL.

  • Không cần xin lại chứng chỉ.

  • Thời gian khôi phục nhanh.


Kết luận

Certbot là công cụ mạnh, nhưng chỉ thực sự phát huy hiệu quả khi:

  • Được đặt đúng vị trí trong kiến trúc,

  • Được sử dụng có kiểm soát,

  • Gắn với chiến lược vận hành lâu dài.

Trong hệ thống nhiều website và web application, HTTPS + Certbot phải là nền tảng ổn định, không phải điểm gây rủi ro.

 

Ví dụ 1 — Web application (khuyến nghị cho QLCL/KHTH/Nhân sự/Thiết bị…)

##
# WebApp: QLCL
# Backend: QMS (10.10.10.66)
# Notes:
# - HTTPS terminate at Reverse Proxy
# - HTTP -> HTTPS redirect
# - Uses standardized snippets
##
# --------- 80 / HTTP: redirect to HTTPS ----------
server {
   listen 80;
   server_name qlcl.example.com;
   # Optional (recommended): allow ACME challenge path if later you use webroot method
   location ^~ /.well-known/acme-challenge/ {
       root /var/www/_letsencrypt;
       allow all;
   }
   return 301 https://$host$request_uri;
}
# --------- 443 / HTTPS: reverse proxy to backend ----------
server {
   listen 443 ssl http2;
   server_name qlcl.example.com;
   # --- Let's Encrypt certificate (created by certbot) ---
   ssl_certificate     /etc/letsencrypt/live/qlcl.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/qlcl.example.com/privkey.pem;
   # --- SSL policy (your standardized snippets) ---
   include snippets/ssl/ssl-common.conf;
   include snippets/ssl/ssl-params.conf;
   # --- Security headers (standardized) ---
   include snippets/headers/security-headers.conf;
   # --- Reverse proxy baseline ---
   include snippets/proxy/proxy-common.conf;
   # --- WebApp-specific proxy tuning: timeouts, upload size ---
   include snippets/proxy/proxy-webapp.conf;
   # If behind Cloudflare for this domain, enable these (otherwise keep commented)
   # include snippets/ssl/ssl-cloudflare.conf;
   # include snippets/headers/real-ip.conf;
   location / {
       proxy_pass http://10.10.10.66;  # QMS primary
   }
}

Ví dụ 2 — Website thường (CMS/website cơ sở y tế)

##
# Website: benhvienabc.vn
# Type: Public website (CMS)
# Backend: QMS (10.10.10.66)
##
server {
   listen 80;
   server_name benhvienabc.vn www.benhvienabc.vn;
   location ^~ /.well-known/acme-challenge/ {
       root /var/www/_letsencrypt;
       allow all;
   }
   return 301 https://$host$request_uri;
}
server {
   listen 443 ssl http2;
   server_name benhvienabc.vn www.benhvienabc.vn;
   ssl_certificate     /etc/letsencrypt/live/benhvienabc.vn/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/benhvienabc.vn/privkey.pem;
   include snippets/ssl/ssl-common.conf;
   include snippets/ssl/ssl-params.conf;
   include snippets/headers/security-headers.conf;
   include snippets/proxy/proxy-common.conf;
   location / {
       proxy_pass http://10.10.10.66;
   }
}

Các file cấu hình include snippets đã đề cập ở bài trước: Bài 8.2. Chuẩn hóa snippets và cấu hình dùng chung cho hàng trăm website