Security

Cách gắn chứng chỉ SSL vào NGINX trên VPS

SSH vào VPS, gõ lệnh nginx -t và thấy "syntax is ok" là chuyện bình thường. Nhưng khi mở trình duyệt, thanh địa chỉ vẫn hiện "Not secure" thì vấn đề nằm ở chỗ bạn chưa gắn chứng chỉ SSL vào NGINX trên VPS. Bài này sẽ hướng dẫn bạn làm điều đó trên Ubuntu 24.04 LTS với Certbot, từ cài đặt, cấu hình đến gia hạn tự động, kèm cách xử lý các lỗi hay gặp nhất.

Yêu cầu trước khi bắt đầu

  • VPS chạy Ubuntu 24.04 LTS (hoặc Debian 12) với user có quyền sudo.
  • NGINX đã được cài đặt và hoạt động, port 80 và 443 đã mở trên firewall.
  • Tên miền đã trỏ A record về IP của VPS.
  • Phiên bản Certbot sử dụng trong bài là 5.7.0 (phát hành 15/07/2026), bản mới nhất tại thời điểm viết.

Vì sao nên dùng Certbot cho NGINX?

Certbot là công cụ chính thức từ Let's Encrypt, tự động hóa toàn bộ quá trình xin chứng chỉ, cấu hình NGINX và gia hạn. Plugin nginx của Certbot sẽ tự dò tìm server block, cài SSL và sửa cấu hình cho bạn. Cách thủ công với OpenSSL vẫn hoạt động, nhưng với số lượng site nhiều hoặc chứng chỉ wildcard, Certbot giúp tiết kiệm thời gian đáng kể và tránh sai sót.

Trong bài này, mình dùng plugin nginx cho trường hợp đơn giản, sau đó nói thêm về cách dùng --webroot khi bạn có cấu hình phức tạp. Còn chứng chỉ wildcard cần DNS challenge, mình đã có bài riêng về chủ đề tự động cấp và gia hạn SSL wildcard với acme.sh.

Bước 1 - Cài đặt Certbot và plugin NGINX

Cập nhật package và cài Certbot cùng plugin NGINX. Trên Ubuntu 24.04, tên gói plugin là python3-certbot-nginx.

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

Sau khi cài xong, kiểm tra phiên bản để chắc chắn Certbot đã sẵn sàng:

certbot --version

Output mong đợi sẽ là certbot 5.7.0 hoặc cao hơn, tùy thời điểm bạn cài.

Bước 2 - Xin chứng chỉ SSL và cấu hình tự động

Đảm bảo NGINX đang chạy và có server block cho tên miền của bạn. Nếu chưa có, hãy tạo một file cấu hình đơn giản tại /etc/nginx/sites-available/ trước khi chạy lệnh bên dưới. Nếu bạn chưa từng cài NGINX, bài cài đặt Nginx làm reverse proxy trên VPS chi tiết 2026 sẽ giúp bạn chuẩn bị nền tảng.

Chạy lệnh sau, thay example.com bằng tên miền thật của bạn. Nếu muốn cấp cho cả www, thêm cả hai vào lệnh:

sudo certbot --nginx -d example.com -d www.example.com

Certbot sẽ hỏi email nhận thông báo hết hạn và điều khoản dịch vụ. Khi được hỏi "Which names would you like to activate HTTPS for?", bạn chỉ cần Enter để chọn tất cả. Cuối cùng, khi được hỏi có redirect HTTP sang HTTPS không, chọn 2 để bật chuyển hướng.

Nếu mọi thứ suôn sẻ, bạn sẽ thấy thông báo thành công với dòng Congratulations! Your certificate and chain have been saved at.... NGINX đã được tự động cấu hình lại.

Xác minh nhanh bằng cách mở trang web với https:// trong trình duyệt hoặc dùng lệnh:

curl -I https://example.com

Output phải có HTTP/2 200 hoặc HTTP/1.1 200 OK và dòng SSL certificate verify ok nếu bạn dùng thêm flag -v. Bạn có thể kiểm tra chi tiết cert bằng lệnh:

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

Output cho thấy notBeforenotAfter của chứng chỉ, xác nhận nó đang hoạt động đúng.

Bước 3 - Kiểm tra cấu hình NGINX sau khi gắn SSL

Sau khi Certbot chạy, nó tự thêm các dòng cấu hình SSL vào server block của bạn. Bạn nên mở file cấu hình ra xem để hiểu những gì đã được thêm:

sudo nano /etc/nginx/sites-available/example.com

Bạn sẽ thấy hai block server: một cái lắng nghe port 80 và redirect sang HTTPS, một cái lắng nghe port 443 với các dòng:

listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

Đây là cấu hình mặc định an toàn. Nếu bạn muốn tinh chỉnh thêm (như bật HTTP/3 hoặc Brotli), hãy xem bài bật HTTP/3 và nén Brotli trên Nginx 2026.

Trước khi reload NGINX, luôn kiểm tra cú pháp:

sudo nginx -t

Output mong đợi: syntax is oktest is successful. Nếu có lỗi, NGINX sẽ chỉ ra dòng cụ thể, bạn sửa rồi kiểm tra lại. Sau đó reload để áp dụng thay đổi:

sudo systemctl reload nginx

Bước 4 - Cấu hình gia hạn tự động

Chứng chỉ Let's Encrypt chỉ có giá trị 90 ngày. May mắn là Certbot cài sẵn systemd timer để tự gia hạn. Kiểm tra trạng thái của timer:

sudo systemctl status certbot.timer

Nếu thấy active (waiting), timer đang chạy và sẽ tự kiểm tra gia hạn 2 lần mỗi ngày. Certbot chỉ gia hạn khi chứng chỉ còn dưới 30 ngày, nên bạn không phải làm gì thêm.

Để chắc chắn quá trình gia hạn hoạt động, bạn có thể chạy thử ở chế độ dry-run. Lệnh này không cấp chứng chỉ mới mà chỉ kiểm tra toàn bộ quy trình:

sudo certbot renew --dry-run

Output mong đợi: dòng Congratulations, all simulated renewals succeeded. Nếu gặp lỗi, hãy xem log để chẩn đoán:

sudo tail -f /var/log/letsencrypt/letsencrypt.log

Xử lý lỗi thường gặp

Một số lỗi mình gặp khá nhiều khi hỗ trợ người dùng gắn SSL cho NGINX:

Lỗi "Could not automatically find a matching server block"

Khi chạy certbot --nginx, Certbot không tìm thấy server block khớp với tên miền bạn cung cấp. Kiểm tra lại tên miền trong lệnh có khớp chính xác với server_name trong file cấu hình NGINX. Hoặc có thể server block của bạn nằm trong file không đúng thư mục sites-available và chưa được symlink vào sites-enabled:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Lỗi "too many certificates" hoặc "rate limit"

Let's Encrypt giới hạn 5 chứng chỉ mỗi tuần cho mỗi tên miền. Nếu bạn thử xin/xóa/xin lại liên tục, sẽ bị chặn. Giải pháp: chờ hết giới hạn hoặc dùng staging để test:

sudo certbot --nginx -d example.com --staging

Staging dùng chứng chỉ không hợp lệ nhưng không tính vào rate limit, phù hợp để test cấu hình.

Lỗi "Failed to connect to host" khi xin chứng chỉ

HTTP challenge của Certbot cần kết nối đến website qua port 80. Nếu firewall chặn port 80 hoặc NGINX không chạy, challenge sẽ thất bại. Kiểm tra firewall:

sudo ufw status

Nếu dùng UFW, đảm bảo có rule cho Nginx Full:

sudo ufw allow 'Nginx Full'

Nếu dùng firewalld trên AlmaLinux thì cú pháp khác, nhưng nguyên tắc giống nhau: phải mở port 80 và 443.

Gắn SSL thủ công cho trường hợp đặc biệt

Trong một số trường hợp - ví dụ website chạy trên cổng khác 80, hoặc cấu trúc thư mục phức tạp - plugin --webroot sẽ phù hợp hơn. Cách này không tự sửa cấu hình NGINX, bạn phải tự thêm các dòng SSL vào server block.

Xin chứng chỉ bằng webroot:

sudo certbot certonly --webroot -w /var/www/example.com -d example.com

Trong đó /var/www/example.com là thư mục gốc website của bạn. Sau khi có chứng chỉ, mở file cấu hình NGINX và thêm block server cho port 443 như đã nói ở Bước 3, rồi reload NGINX. Cách này cho bạn toàn quyền kiểm soát nhưng mất công hơn, và bạn phải tự nhớ gia hạn.

Chọn loại chứng chỉ SSL phù hợp

Let's Encrypt miễn phí và đáp ứng tốt nhu cầu cơ bản, nhưng không phải lúc nào cũng là lựa chọn tối ưu. Nếu bạn cần chứng chỉ DV với thời gian xác minh nhanh, hoặc wildcard cho nhiều subdomain, có thể xem các gói chứng chỉ SSL giá rẻ từ GoGetSSL. Với các hệ thống doanh nghiệp cần bảo hành pháp lý hoặc hiển thị tên công ty, chứng chỉ OV/EV sẽ phù hợp hơn.

Điểm quan trọng nhất là chứng chỉ SSL phải được gia hạn đúng hạn. Với Let's Encrypt, timer tự động lo việc đó. Với chứng chỉ trả phí, bạn phải có kế hoạch nhắc gia hạn, nếu không website sẽ báo lỗi bảo mật và mất uy tín với khách hàng. Nếu đang chạy hệ thống quan trọng, hãy thiết lập cảnh báo sớm ít nhất 15 ngày trước khi hết hạn.

Câu hỏi thường gặp

Gắn chứng chỉ SSL vào NGINX trên VPS có mất phí không?

Không, nếu bạn dùng Let's Encrypt qua Certbot. Chứng chỉ hoàn toàn miễn phí, tự động gia hạn, và được mọi trình duyệt công nhận. Bạn chỉ mất chi phí thuê VPS, ví dụ VPS Linux của thueVPS có giá từ khoảng 189.000đ/tháng.

Chứng chỉ Let's Encrypt có an toàn không?

Có. Let's Encrypt là tổ chức được các trình duyệt lớn tin cậy, cấp chứng chỉ DV (Domain Validation) với độ mã hóa tương đương chứng chỉ trả phí. Điểm khác biệt chính là thời hạn 90 ngày và không có bảo hành pháp lý, trong khi chứng chỉ trả phí thường 1-2 năm.

Vì sao website vẫn báo "Not secure" sau khi gắn SSL?

Thường do nội dung hỗn hợp (mixed content): trang web vẫn gọi tài nguyên qua HTTP như ảnh, CSS, JS. Mở DevTools (F12) của trình duyệt, tab Console hoặc Network, tìm các request HTTP còn sót lại và chuyển chúng sang HTTPS. Nếu bạn đã bật redirect ở Bước 2, kiểm tra lại xem rule redirect có hoạt động đúng không.

Có cần thay đổi gì khi website chạy nhiều subdomain?

Nếu các subdomain cùng một tên miền gốc (vd blog.example.com, api.example.com), bạn có thể dùng chứng chỉ wildcard *.example.com. Certbot hỗ trợ wildcard qua DNS challenge. Với plugin --nginx thông thường sẽ không hoạt động, bạn cần dùng acme.sh hoặc cấu hình DNS plugin riêng, chi tiết có trong bài tự động cấp và gia hạn SSL wildcard với acme.sh.

SSL có làm chậm website không?

Hiện tại thì không đáng kể. Giảm thời gian thực tế rất nhỏ nhờ HTTP/2 và TLS 1.3. Thực tế, HTTPS còn giúp tăng tốc vì cho phép dùng HTTP/2 (yêu cầu bắt buộc), giúp tải song song nhiều tài nguyên hơn so với HTTP/1.1.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.