Lỗi Gặp Phải
Nginx từ chối khởi động hoặc reload, và bạn thấy thông báo này trong logs:
nginx: [emerg] cannot load certificate "/etc/nginx/ssl/cert.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory)
Đường dẫn trong thông báo lỗi khớp với giá trị bạn đặt trong ssl_certificate của file cấu hình Nginx. Lời gọi OpenSSL bên dưới là BIO_new_file() đã thất bại. Điều này thường có ba nguyên nhân: file không tồn tại tại đường dẫn đó, Nginx không đọc được file, hoặc đường dẫn bị sai.
Nguyên Nhân Gốc Rễ
- File certificate đơn giản là không tồn tại tại đường dẫn đã cấu hình
- Đường dẫn trong
nginx.confbị gõ nhầm hoặc trỏ đến vị trí sai - File tồn tại nhưng thuộc sở hữu của root và không thể đọc được bởi user
www-data/nginx - Symlink trỏ đến cert bị hỏng (thường xảy ra sau khi gia hạn Let's Encrypt)
- Cert được lưu trên một volume được mount mà chưa được mount tại thời điểm khởi động
Cách Sửa 1: Xác Nhận File Có Thực Sự Tồn Tại Không
Bắt đầu từ điều đơn giản nhất — file có thực sự tồn tại tại đường dẫn đó không?
ls -la /etc/nginx/ssl/cert.pem
Nếu lệnh trả về No such file or directory, file đang bị thiếu. Hãy kiểm tra xem certificate của bạn thực sự nằm ở đâu:
# Cert của Let's Encrypt nằm ở đây:
ls -la /etc/letsencrypt/live/yourdomain.com/
# Output thường thấy của Certbot / acme.sh:
# cert.pem chain.pem fullchain.pem privkey.pem
Đang dùng Let's Encrypt? Hãy trỏ ssl_certificate đến fullchain.pem, không phải cert.pem. Nginx cần toàn bộ chuỗi certificate — chỉ có cert lá sẽ gây lỗi TLS handshake với hầu hết các client. Private key thì trỏ đến privkey.pem:
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
Cách Sửa 2: Sửa Lại Đường Dẫn Trong Cấu Hình Nginx
Quét toàn bộ file cấu hình Nginx để tìm directive ssl_certificate:
grep -r 'ssl_certificate' /etc/nginx/
Sau đó cập nhật lại các đường dẫn cho khớp với vị trí thực tế của cert. Ví dụ với cert tự quản lý lưu trong /etc/nginx/ssl/:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# ... phần cấu hình còn lại
}
Sau khi chỉnh sửa, hãy luôn kiểm tra cú pháp trước khi reload:
nginx -t
Cách Sửa 3: Tạo Thư Mục SSL Và Sao Chép Cert Vào
Có cert từ một CA thương mại (ví dụ họ gửi cho bạn file .crt qua email)? Hãy đặt nó vào đúng chỗ:
# Tạo thư mục nếu chưa có
mkdir -p /etc/nginx/ssl
# Sao chép các file certificate
cp yourdomain.crt /etc/nginx/ssl/cert.pem
cp yourdomain.key /etc/nginx/ssl/privkey.pem
# Đặt quyền truy cập hạn chế
chmod 600 /etc/nginx/ssl/privkey.pem
chmod 644 /etc/nginx/ssl/cert.pem
chown root:root /etc/nginx/ssl/privkey.pem
Cách Sửa 4: Kiểm Tra Symlink Bị Hỏng (Let's Encrypt)
Let's Encrypt lưu cert đang dùng dưới dạng symlink trỏ vào /etc/letsencrypt/archive/. Một lần gia hạn thất bại có thể để lại symlink trỏ đến file không còn tồn tại:
# Kiểm tra xem symlink có hợp lệ không
ls -la /etc/letsencrypt/live/yourdomain.com/
# Symlink bị hỏng trông như thế này:
# cert.pem -> ../../archive/yourdomain.com/cert3.pem (file không tồn tại)
# Xác minh các file trong archive có tồn tại không
ls -la /etc/letsencrypt/archive/yourdomain.com/
Nếu các file trong archive đã biến mất, hãy buộc gia hạn lại:
certbot renew --force-renewal -d yourdomain.com
Hoặc nếu bạn đang dùng acme.sh:
acme.sh --renew -d yourdomain.com --force
Cách Sửa 5: Sửa Quyền Truy Cập File
File đã có đó — nhưng Nginx không mở được. Hãy tìm xem Nginx worker đang chạy với user nào:
ps aux | grep nginx | grep -v grep
# Tìm user của tiến trình worker (www-data, nginx, hoặc nobody)
Sau đó kiểm tra xem user đó có thực sự đọc được cert không:
# Với Ubuntu/Debian (user www-data)
sudo -u www-data cat /etc/nginx/ssl/cert.pem
# Với CentOS/RHEL (user nginx)
sudo -u nginx cat /etc/nginx/ssl/cert.pem
Nếu bị từ chối truy cập, hãy điều chỉnh lại quyền. Cert có thể để mọi người đọc được; private key thì không nên:
chmod 644 /etc/nginx/ssl/cert.pem
chmod 640 /etc/nginx/ssl/privkey.pem
chown root:www-data /etc/nginx/ssl/privkey.pem
Với Let's Encrypt, Nginx còn cần quyền thực thi trên các thư mục live/ và archive/ để theo được symlink. Nếu thiếu quyền này, quá trình duyệt thư mục sẽ thất bại âm thầm:
chmod 755 /etc/letsencrypt/live/
chmod 755 /etc/letsencrypt/archive/
chmod 755 /etc/letsencrypt/archive/yourdomain.com/
Kiểm Tra Sau Khi Sửa
Trước khi động vào Nginx, hãy chạy kiểm tra cú pháp cấu hình:
nginx -t
# Kết quả mong đợi:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
Khi đã qua được kiểm tra, hãy reload (hoặc restart nếu Nginx đã bị dừng hẳn):
# Reload instance đang chạy
systemctl reload nginx
# Hoặc restart nếu đã bị dừng
systemctl restart nginx
# Xác nhận đang chạy
systemctl status nginx
Giờ hãy xác nhận HTTPS hoạt động đúng từ đầu đến cuối:
curl -I https://yourdomain.com
# Nên trả về HTTP/2 200 (hoặc 301/302), không phải lỗi kết nối
# Kiểm tra thông tin chi tiết của certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null 2>&1 | grep -E 'subject|issuer|expire'
Phòng Ngừa
- Dùng đường dẫn tuyệt đối trong
ssl_certificate— không bao giờ dùng đường dẫn tương đối. - Móc vào quá trình gia hạn cert: đặt một script chứa lệnh
nginx -t && systemctl reload nginxvào thư mục/etc/letsencrypt/renewal-hooks/deploy/để Nginx tự động reload sau mỗi lần gia hạn thành công. - Phát hiện lỗi gia hạn sớm: chạy
certbot renew --dry-runtrong một cron job hàng tuần — lệnh này mô phỏng quá trình gia hạn mà không thay thế gì cả, giúp bạn biết có lỗi trước khi nó gây ra downtime. - Tránh lưu cert trên các mount ngoài: nếu bắt buộc phải làm vậy, hãy thêm
RequiresMountsFor=vào unit systemd của Nginx để nó chờ mount sẵn sàng trước khi khởi động.

