composer 2.5+ 报 curl error 60 的根本原因是 openssl 无法加载 ssl.cafile 配置的证书链,需确保 pem 格式、完整证书链(中间 ca+根 ca)、无 bom/空行/注释,并用 --global 全局配置且 php 进程有读取权限。

Composer 2.0+ 默认强制 HTTPS,但私有仓库证书不被信任时,cURL error 60: SSL certificate problem 仍会高频出现——问题不在“是否走 HTTPS”,而在于“能否验证证书”。关键不是开关配置,是让 OpenSSL 认出你的 CA。
为什么设置了 ssl.cafile 还报 cURL error 60?
根本原因:Composer ≥2.5 不再简单透传 ssl.cafile 给 cURL,而是先用它初始化 OpenSSL 上下文;一旦路径错、格式错、权限不足,就静默 fallback 到系统默认 CA,然后继续报错——你根本看不到“配置加载失败”的提示。
常见踩坑点:
-
ssl.cafile指向的是单个.crt(比如公司内网导出的 Windows.cer),但 OpenSSL 要求 PEM 格式且必须含完整链(中间 CA + 根 CA) - 手动用文本编辑器拼接证书,混入 BOM、空行或注释,导致
openssl x509 -in ca.pem -text -noout直接失败 - 用了项目级配置
composer config ssl.cafile /path/to/ca.pem,但 CLI 下的composer install是全局进程,根本不读该项目配置 - PHP 进程(如
www-data)无权读取家目录下的证书文件,尤其在容器或 nginx/php-fpm 场景下
如何生成 Composer 可识别的 PEM 证书链文件?
必须确保文件是 OpenSSL 能解析的纯 PEM 合并链,顺序为:中间 CA 在前,根 CA 在后。别手拼,用 cat 安全合并:
cat intermediate.crt root.crt > company-ca.pem
验证是否有效:
openssl x509 -in company-ca.pem -text -noout
如果报错 “unable to load certificate”,说明文件不是 PEM 或内容损坏。补救方式:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 若原始是 DER 格式(如
.cer),先转 PEM:openssl x509 -inform DER -in your-ca.cer -outform PEM -out ca.pem - 确认无多余空行、无 UTF-8 BOM(可用
file -i company-ca.pem检查编码) - 不要包含任何非证书内容(比如
-----BEGIN RSA PRIVATE KEY-----或注释文字)
必须用 --global 配置 ssl.cafile
项目级 composer.json 中的 config.ssl.cafile 对 HTTPS 仓库认证无效——它只影响部分本地路径解析,不参与网络层 TLS 握手。
正确做法是全局设置,并确认生效:
composer config --global ssl.cafile /etc/ssl/certs/company-ca.pem
composer config --global --list | grep ssl.cafile
输出应为实际路径。若你无法将证书放系统路径(如受限 CI 环境),可改用 PHP 层控制:
- 在
php.ini中设openssl.cafile=/path/to/company-ca.pem(推荐) - 或设
curl.cainfo=/path/to/company-ca.pem,效果等同 - 改完需重启 PHP 进程(CLI 下执行
php --ini确认配置已加载)
secure-http=true 是默认值,别白配
composer config -g secure-http true 几乎没意义——Composer 2.0+ 默认就是 true。真要检查,运行 composer config -g secure-http,输出 true 即可。
真正该做的只有两件事:
- 删掉
composer.json中所有http://开头的仓库 URL,全部换为https:// - 确认私有仓库地址(如
https://pkg.example.com)能被curl -vI https://pkg.example.com/packages.json正常访问(含证书验证通过)
如果 curl 都过不去,Composer 必然失败;别急着调 composer 配置,先解决底层 OpenSSL 信任链。










