直接检查PEM文件内容和编码状态是最快定位证书链格式问题的方法:需确认其为纯ASCII文本、无BOM或CRLF换行,首行为标准-----BEGIN CERTIFICATE-----;fullchain.pem必须按域名证书→中级CA证书顺序拼接,禁含根证书或私钥;用openssl verify -CAfile fullchain.pem domain.crt验证链完整性,并校验证书与私钥模数一致;Nginx配置中ssl_certificate须指向fullchain.pem,私钥权限为600,且SELinux/Docker挂载路径需正确。

直接检查 PEM 文件内容和编码状态,是最快速定位证书链格式问题的方法。Nginx 对 PEM 文件极其敏感——哪怕开头多一个空格、换行是 Windows 风格(CRLF)、或文件带 BOM 头,都会导致 PEM_read_bio 类错误,甚至静默降级为 HTTP。
确认 PEM 文件是否为纯文本且无隐藏字符
证书和私钥都必须是标准 ASCII 文本,不能含 UTF-8 BOM 或不可见控制符:
- 用
file your_cert.pem检查输出,正确应显示 ASCII text;若出现 UTF-8 Unicode (with BOM) text,说明被记事本等工具污染,需用 VS Code / vim 保存为 UTF-8 无 BOM 格式 - 用
cat -A your_cert.pem查看隐藏符号:如果看到 ^M(即 CRLF 换行),说明是 Windows 换行,运行dos2unix your_cert.pem修复 - 用
head -n 5 your_cert.pem确认首行确实是 -----BEGIN CERTIFICATE-----(注意前后各两个短横,大小写一致,无空格)
验证证书链拼接顺序是否合规
Nginx 的 ssl_certificate 必须指向一个按逻辑顺序拼接的 fullchain.pem,不是单个域名证书:
- 打开该文件,第一段必须是你的域名证书(
Subject: CN=yourdomain.com) - 第二段起应为中级 CA 证书(如 Let’s Encrypt R3、Sectigo RSA Domain Validation Secure Server CA),不能把根证书或私钥混入
- 不要加入
ca-bundle.crt或 root.crt —— Nginx 不需要也不识别根证书,加了反而破坏链验证 - 推荐拼接命令:
cat domain.crt intermediate.crt > fullchain.pem,顺序不可颠倒
用 OpenSSL 命令做链完整性校验
这是判断证书链是否真正可被客户端信任的关键一步:
- 执行:
openssl verify -CAfile fullchain.pem domain.crt - 返回 OK 表示链完整、顺序正确、签名有效
- 若报错如 unable to get local issuer certificate,说明缺中级证书;若报 self signed certificate in certificate chain,说明误把根证书加进去了
- 额外检查私钥是否匹配:
openssl x509 -noout -modulus -in domain.crt | openssl md5和openssl rsa -noout -modulus -in private.key | openssl md5,两行 MD5 值必须完全一致
检查 Nginx 配置与文件权限是否协同生效
即使 PEM 内容完美,配置或系统层限制也会让 Nginx 读不到正确内容:
-
ssl_certificate必须指向 fullchain.pem,不是cert.pem;ssl_certificate_key单独指向 private.key - 私钥权限必须是 600(
chmod 600 private.key),证书链文件建议 644 - SELinux 启用时可能拦截读取,临时测试可用
setenforce 0排除;AppArmor 用户检查对应 profile 是否放行证书路径 - Docker 环境下务必核对 volume 挂载路径是否准确映射到容器内 Nginx 配置所写的绝对路径


















