必须用绝对路径指向完整 PEM 链文件,且优先走 composer config --global cafile;因该配置作用于所有项目和 CLI 调用,优先级高于 php.ini 的 openssl.cafile,而相对路径、权限不足、BOM/换行符或中文域名未转 Punycode 均会导致静默失效。

必须用绝对路径指向完整 PEM 链文件,且优先走 composer config --global cafile,否则 CI、Docker 或多用户环境大概率静默失败。
为什么 composer.json 里配 options.ssl.cafile 经常不生效
这个配置只作用于对应 repositories 条目,且路径必须是绝对路径——./certs/ca.pem 或 certs/ca.pem 在 CI/CD 容器或 PHP-FPM 下基本无效,因为 Composer 不解析相对路径,直接透传给 PHP 的 stream_context,而后者对相对路径行为不一致。
常见错误现象:
- 本地开发能过,CI 报
cURL error 60: SSL certificate problem - PHP 进程属主(如
www-data)无权读取证书文件,但错误不提示权限问题,只报证书验证失败 - 证书文件里混入 Windows 换行符、BOM 或空行,导致 OpenSSL 解析失败,Composer 静默忽略该配置
composer config --global cafile 怎么设才真正生效
这是最推荐的配置方式,影响所有项目和 CLI 调用,且优先级高于 php.ini 中的 openssl.cafile(注意:不是 curl.cainfo)。
实操要点:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 路径必须是绝对路径,例如:
/etc/ssl/certs/internal-ca.pem,不能用~或环境变量 - 执行后用
composer config --global --list | grep cafile确认输出是否为预期路径 - 证书文件需满足:以
-----BEGIN CERTIFICATE-----开头,包含中间 CA + 根 CA(顺序:中间在前、根在后),不含注释或多余空行 - 权限设为
644,属主建议为运行 PHP CLI 的用户(如root或www-data),避免因权限被 OpenSSL 拒绝加载
中文域名私有源必须转 Punycode 才能匹配证书
如果私有仓库地址是 https://pkg.公司名.内部,即使证书链正确、路径无误,也会报 unable to get local issuer certificate —— 因为 OpenSSL 域名匹配逻辑不支持原生中文 IDN,必须先转成 Punycode 格式。
验证方法:
- 用
curl -v --cacert /path/to/chain.pem https://xn--55qx5d.内部测试是否返回HTTP 200且无证书警告 - 确认私有源服务器证书的
Subject Alternative Name字段已包含该 Punycode 域名(而非中文原始域名) - 若用 Nginx/Apache 配置 HTTPS,确保
ssl_certificate指向的证书含该 SAN 条目
Docker 和 CI 环境最容易漏掉的三件事
容器或自动化流水线里,证书信任链失效往往不是配置错了,而是运行时上下文缺失:
- 镜像中没装
ca-certificates包(尤其 Alpine),导致系统级 CA 路径为空,Composer fallback 失败 -
composer config --global cafile写入的是宿主机~/.composer/config.json,但容器内运行的是独立用户(如user: 1001),根本没加载该配置 - CI runner 使用非 root 用户执行,但证书文件放在
/root/下,PHP 进程无法读取;应统一放至/etc/ssl/certs/并设好权限
真正关键的不是“有没有配”,而是“PHP 进程启动时能不能在内存里拿到那个 PEM 内容”——路径、权限、格式、编码,四者缺一不可。任何环节出偏差,Composer 都不会报错,只会安静地继续用系统默认 CA,然后失败。

















