PHP OpenSSL无法验证私有仓库SSL证书的根本原因是其信任库未包含私有CA根证书,需将根证书合并进PHP实际使用的cacert.pem文件并配置GIT_SSL_CAINFO环境变量。

私有仓库用 HTTPS 地址但 composer install 报 SSL 证书错误,基本不是仓库本身的问题,而是 PHP 的 OpenSSL/cURL 没法验证你私有域名的证书链——它连“信任谁”都不知道,更别说校验了。
确认 PHP 是否真在用你的私有证书
别急着改 composer.json 或加 --no-secure-http。先让 PHP 自己说清楚它当前认哪些证书:
- 运行
php -r "print_r(openssl_get_cert_locations());",重点看ini_cafile和default_cert_file的路径是否存在、文件是否可读(ls -l /path/to/cacert.pem看大小和权限) - 如果
ini_cafile是空的,说明openssl.cafile根本没在php.ini里配;如果指向一个 4KB 的空文件,那证书链就是断的 - 私有仓库域名(比如
git.your-company.com)的证书如果是自签名或内网 CA 签发的,必须手动加进这个文件,不能指望系统默认包
把私有根证书追加进 cacert.pem
你手里应该有一个 PEM 格式的根证书(以 -----BEGIN CERTIFICATE----- 开头),把它合并进 PHP 正在用的 cacert.pem 文件里,而不是单独设 cafile:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- Linux/macOS:
sudo cat your-company-root.crt >> /etc/ssl/certs/ca-certificates.crt && sudo update-ca-certificates - Windows:用文本编辑器打开
cacert.pem(比如C:\php\extras\ssl\cacert.pem),把你的根证书内容粘贴到底部,保存 - macOS(Homebrew):证书文件通常在
/opt/homebrew/etc/openssl@3/cert.pem,直接追加后无需额外命令 - 改完后必须新开终端再试 —— CLI 模式下 PHP 进程不热加载证书配置
为什么 composer config --global cafile 不起作用
composer config --global cafile 只影响 Composer 自己封装的 HTTP 客户端,但私有仓库克隆时,Composer 实际调用的是 Git 命令(git clone https://...),而 Git 默认走系统 cURL 或 OpenSSL,完全无视 Composer 的 cafile 设置:
- Git 本身不读
php.ini,但它会继承系统环境变量:export GIT_SSL_CAINFO=/path/to/cacert.pem(Linux/macOS)或set GIT_SSL_CAINFO=C:\php\extras\ssl\cacert.pem(Windows) - 如果你用的是 SSH 方式(
git@your-company.com:repo.git),那就彻底绕过 SSL 验证问题,但前提是已配好 SSH key 并ssh -T git@your-company.com能通 -
composer config --global github-oauth对私有 GitLab/Gitee/自建 Gogs 无效,它只认github.com
检查私有仓库 URL 和 type 配置是否合法
即使证书全对,composer.json 里写错一个字符也会让 Composer 放弃走你配的源,默默 fallback 到 packagist.org,然后报一堆 SSL 错误:
- URL 必须是完整 HTTPS 地址,末尾不加
/(和镜像源不同):"url": "https://git.your-company.com/group/repo.git" -
type必须是vcs,不是package或留空;否则 Composer 不会尝试克隆 - 确保没有全局
repositories配置覆盖项目级设置:运行composer config --list | grep repositories,看到重复项就用composer config --unset repositories清掉 - 验证真实行为:
composer install -vvv 2>&1 | grep -E "(Cloning|Downloading)",第一行输出的 URL 才是你真正连的地址
最容易被忽略的一点:私有仓库证书的 Subject Alternative Name (SAN) 必须包含你实际访问的域名,比如用了 git.internal 但证书只签了 git.your-company.com,OpenSSL 就会拒绝——这种错误不会提示“域名不匹配”,只会笼统报 certificate verify failed。

















