Composer私有仓库连接失败需分层排查:先用composer update -vvv区分HTTP(401)或Git层(Permission denied)错误;再手动curl验证packages.json、git ls-remote验权限;最后检查auth.json路径/域名匹配及CI凭据透传。

Composer 私有仓库连接失败无法靠 composer install 一次执行就定位根源——它会在 HTTP 层或 Git 层静默卡住、报 401/404,却不告诉你到底是 token 过期、域名配错,还是凭据根本没加载。必须分层主动探测。
用 composer update -vvv 快速区分 HTTP 和 Git 层失败
这是最直接的判断入口。加 -vvv 后观察最后几行输出:
- 如果出现
Failed to download https://repo.example.com/packages.json: The "https://repo.example.com/packages.json" file could not be downloaded (HTTP status 401),说明是 HTTP 鉴权失败,问题在auth.json的http-basic配置或 OAuth token - 如果卡在
Executing command (CWD): git clone --no-checkout ...,且后续无进展或报Permission denied (publickey),说明是 Git 层凭据问题:SSH 密钥未加载,或 HTTPS 凭据未缓存 - 如果既没 HTTP 报错也没 Git 命令,而是直接跳到
Package not found,大概率是repositories配置被忽略(type不对、URL 缺斜杠、{"packagist.org": false}没放对位置)
手动模拟 Composer 的两个关键请求
Composer 在安装前只做两件事:GET packages.json,再根据结果决定是否 git clone。把这两步拆出来单独验证,就能绕过 Composer 的封装干扰:
- HTTP 层:运行
curl -I -u "token:" https://repo.example.com/packages.json(注意-u "token:"是 OAuth 场景的标准写法;Basic Auth 则用-u "user:pass") - Git 层:
git ls-remote https://gitlab.example.com/org/pkg.git HEAD(HTTPS)或git ls-remote git@gitlab.company:org/pkg.git HEAD(SSH)——这个命令不下载代码,只验连通性和权限,快且干净 - Windows 用户若用 HTTPS,记得先执行
git config --global credential.helper store,否则git ls-remote会卡在用户名输入
检查 auth.json 是否真被加载且匹配
很多人改了 auth.json 却没生效,是因为路径、域名或环境变量覆盖导致配置未命中:
- 运行
composer config --global --list | grep -i auth,确认输出里有你预期的http-basic或github-oauth条目 - 检查 URL 域名是否完全一致:比如仓库地址是
https://repo.internal/,但auth.json里写的是"internal.example.com",就不会匹配 - 留意
COMPOSER_AUTH环境变量——它会完全覆盖auth.json,CI 中常因注入方式错误(如多了一层 JSON 转义)导致凭据为空 - GitHub/GitLab token 可直接验证:
curl -H "Authorization: token xxxxx" https://api.github.com/user或curl "https://gitlab.example.com/api/v4/user?private_token=xxxxx"
CI 环境下最容易被忽略的凭据透传问题
本地能通、CI 报 401,90% 是凭据没传进去,而非配置本身错:
- Docker 构建中,
~/.composer/auth.json不会自动挂载——必须显式-v $(pwd)/.composer/auth.json:/root/.composer/auth.json:ro - GitHub Actions 中,不要把 token 写死在脚本里;用
${{ secrets.PACKAGIST_TOKEN }}注入,并通过composer config http-basic.repo.example.com ${{ secrets.USER }} ${{ secrets.TOKEN }}动态写入 - Git SSH 方式在 CI 中需额外步骤:确保
known_hosts已预置(避免首次连接交互),且私钥已用ssh-add加载(chmod 600私钥文件是前提) - 所有凭据类操作,建议在 CI 步骤开头加一句
composer diagnose——它会真实复现安装时的网络链路,比任何单点 curl 更可靠
真正难处理的不是某次失败,而是凭据状态不可见:token 可能过期、SSH 密钥可能被吊销、镜像源 URL 可能少了个斜杠——这些都不会在 composer install 时报明确提示,只能靠分层探测提前暴露。


















