Lỗi Gặp Phải
Nginx hoặc Apache từ chối khởi động sau khi gia hạn chứng chỉ hoặc migration server:
nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/ssl/private/server.key") failed
(SSL: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)
Hoặc trực tiếp từ OpenSSL:
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
Server không thể khởi động. HTTPS bị sập. Hãy cùng xử lý.
Nguyên Nhân Thực Sự
OpenSSL đã cố load private key của bạn nhưng thất bại. Có ba nguyên nhân gây ra điều này:
- Sai file key — private key không khớp với certificate (phổ biến nhất)
- File PEM bị hỏng hoặc bị cắt bớt — file bị hư hỏng, bị cắt đứt, hoặc bị ghi đè một phần
- Sai định dạng — key ở dạng binary DER thay vì base64 PEM, hoặc thiếu header
Hãy chẩn đoán trước khi hành động — cách xử lý cho mỗi trường hợp hoàn toàn khác nhau.
Bước 1: Kiểm Tra Xem Key Có Khớp Với Certificate Không
Chạy cả hai lệnh và so sánh kết quả MD5. Hash giống nhau nghĩa là key và cert của bạn là một cặp hợp lệ:
# Fingerprint của certificate
openssl x509 -noout -modulus -in /etc/ssl/certs/server.crt | openssl md5
# Fingerprint của private key
openssl rsa -noout -modulus -in /etc/ssl/private/server.key | openssl md5
Kết quả khớp trông như thế này:
(stdin)= a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
(stdin)= a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 ← giống nhau = đúng
Hash khác nhau? Cặp không khớp. Bỏ qua thẳng đến Bước 3.
Bước 2: Xác Minh File PEM Không Bị Hỏng
Thử load trực tiếp key:
openssl rsa -in /etc/ssl/private/server.key -check
Một key bình thường sẽ in ra:
RSA key ok
Bất kỳ lỗi nào ở đây nghĩa là file bị hỏng, hoặc ngay từ đầu nó chưa bao giờ là file PEM key hợp lệ.
Cũng nên kiểm tra nhanh ranh giới của file:
head -1 /etc/ssl/private/server.key
tail -1 /etc/ssl/private/server.key
Một file RSA key hợp lệ:
-----BEGIN RSA PRIVATE KEY-----
...base64 content...
-----END RSA PRIVATE KEY-----
Định dạng PKCS#8 (dùng bởi các công cụ mới hơn và ECDSA keys):
-----BEGIN PRIVATE KEY-----
...base64 content...
-----END PRIVATE KEY-----
Nếu thấy ký tự binary lộn xộn hoặc thiếu footer nghĩa là file bị hỏng. Hãy khôi phục từ backup hoặc cấp lại certificate.
Bước 3: Xử Lý Key Và Certificate Không Khớp
Key và cert đến từ các lần cấp phát khác nhau. Tình huống phổ biến nhất: bạn gia hạn cert nhưng certificate mới lại được đặt ở đường dẫn khác, trong khi key cũ vẫn còn đó. Hoặc script deploy lấy cert từ tháng này nhưng key lại từ gói của quý trước.
Phương án A — Bạn vẫn còn private key gốc ở đâu đó
Kiểm tra vị trí backup của bạn, máy tạo ra CSR, hoặc kho lưu trữ bí mật (HashiCorp Vault, GitHub Secrets, AWS Secrets Manager). Khi tìm thấy, hãy xác minh sự khớp trước khi động vào bất cứ thứ gì trên môi trường production:
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in recovered.key | openssl md5
Khi chúng khớp, đặt vào đúng vị trí và reload:
cp recovered.key /etc/ssl/private/server.key
chmod 600 /etc/ssl/private/server.key
nginx -t && systemctl reload nginx
Phương án B — Key đã mất, cấp lại từ đầu
Không có key, không có lối tắt. Tạo cặp key mới, tạo CSR mới, và lấy certificate mới từ CA của bạn:
# Key 2048-bit mới (dùng 4096 cho cert dài hạn)
openssl genrsa -out /etc/ssl/private/server.key 2048
# CSR từ key mới
openssl req -new -key /etc/ssl/private/server.key -out server.csr
Nộp CSR cho Let's Encrypt, DigiCert, hoặc bất kỳ CA nào đã cấp bản gốc. Để tạo cert tự ký nhằm gỡ chặn việc kiểm thử ngay lúc này:
openssl req -x509 -new -nodes \
-key /etc/ssl/private/server.key \
-sha256 -days 365 \
-out /etc/ssl/certs/server.crt
Phương án C — Key ở định dạng DER
Nếu head -1 hiển thị ký tự binary lộn xộn thay vì header -----BEGIN, file đang ở dạng DER. Một lệnh duy nhất để xử lý:
openssl rsa -inform DER -in server.key.der -outform PEM -out /etc/ssl/private/server.key
Bước 4: Sửa Quyền Truy Cập File
Quyền sai gây ra lỗi âm thầm — OpenSSL không thể đọc key nhưng thông báo lỗi không phải lúc nào cũng nói rõ điều đó. Hãy đặt đúng quyền:
# Private key: chỉ root mới được đọc
chmod 600 /etc/ssl/private/server.key
chown root:root /etc/ssl/private/server.key
# Certificate: cho phép đọc công khai là ổn
chmod 644 /etc/ssl/certs/server.crt
Trên Ubuntu, Nginx chạy với tư cách www-data. Key 600 được sở hữu bởi root sẽ chặn hoàn toàn. Cách sửa:
chown root:www-data /etc/ssl/private/server.key
chmod 640 /etc/ssl/private/server.key
Xác Minh Sau Khi Sửa
Kiểm tra cấu hình trước khi reload — đừng để server sập lần thứ hai:
# Nginx
nginx -t
# Apache
apachectl configtest
Sau đó reload:
systemctl reload nginx
# hoặc
systemctl reload apache2
Xác nhận certificate đúng đang thực sự được phục vụ:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates -subject
Bạn sẽ thấy tên domain và ngày hết hạn. Nếu kết quả hiển thị sai domain nghĩa là đường dẫn cert trong cấu hình của bạn vẫn đang trỏ vào file cũ.
Danh Sách Kiểm Tra Nhanh
- MD5 modulus của cert và key phải giống hệt nhau — kiểm tra điều này trước tiên, mọi lúc
openssl rsa -in key.pem -checkphải trả về "RSA key ok"- File PEM phải bắt đầu bằng
-----BEGIN ... KEY-----và kết thúc bằng-----END ... KEY----- - Quyền truy cập: 600 (hoặc 640 cho www-data) cho private key, 644 cho cert
- Đường dẫn file key trong cấu hình Nginx/Apache phải khớp chính xác với vị trí file thực tế — kể cả dấu gạch chéo cuối, symlink, tất cả mọi thứ
Tránh Lặp Lại Lần Sau
Tạo key và CSR cùng nhau trong một lệnh, trong cùng một thư mục, với năm trong tên file. Không bao giờ nhầm lẫn file từ các lần cấp phát khác nhau nữa:
openssl req -newkey rsa:2048 -nodes \
-keyout /etc/ssl/private/yourdomain-2026.key \
-out /etc/ssl/csr/yourdomain-2026.csr
Thêm lệnh kiểm tra modulus vào script deployment của bạn. Hai lệnh, mười giây, phát hiện lỗi này mọi lúc mọi nơi.

