GitLab私有库clone失败因Composer未使用SSH密钥,需验证SSH连通性、确保composer.json用SSH格式URL、配置~/.ssh/config匹配主机名、禁用git密码提示并设置正确权限。

GitLab私有库 clone 失败:Permission denied (publickey)
直接用 composer install 或 composer update 拉取 GitLab 私有仓库时,报 Permission denied (publickey),说明 Composer 底层执行 git clone 时没走你本地已配好的 SSH 密钥。根本原因不是 Composer 本身不支持 SSH,而是它默认调用系统 git 命令,而该命令是否能走 SSH,取决于你的 git 配置和 SSH agent 状态。
确保 SSH 密钥已加载且能直连 GitLab
先绕过 Composer,验证基础链路是否通:
- 确认
~/.ssh/id_rsa(或对应私钥)已存在,且公钥已添加到 GitLab 账户的 SSH Keys 设置页 - 运行
ssh -T git@gitlab.com(或你的 GitLab 实例域名,如git@your.gitlab.internal),看到Welcome to GitLab才算成功 - 若提示
Could not open a connection to your authentication agent,需先启动 agent 并添加密钥:eval $(ssh-agent -s) ssh-add ~/.ssh/id_rsa
- 检查
~/.ssh/config是否为 GitLab 主机指定了正确的用户和密钥(尤其当使用非默认密钥名或端口时):Host gitlab.com User git IdentityFile ~/.ssh/id_rsa_gitlab IdentitiesOnly yes
强制 Composer 使用 SSH 协议而非 HTTPS
Composer 默认可能尝试 HTTPS(尤其 composer.json 中 repo URL 写成 https://...),此时即使 SSH 配好了也无用。必须确保:
-
composer.json中的repositories条目或包的source.url是 SSH 格式,形如:git@gitlab.com:group/project.git,而非https://gitlab.com/group/project.git - 如果依赖的是 Packagist 上的包但源被 fork 到私有 GitLab,需在
repositories中显式声明:"repositories": [ { "type": "vcs", "url": "git@gitlab.com:my-group/my-forked-package.git" } ] - 避免混用协议:不要让同一仓库同时出现在 HTTPS 和 SSH 地址中,Composer 可能缓存旧地址,可清缓存:
composer clear-cache
跳过 Git 的交互式密码提示(关键防卡死)
某些环境(如 CI/CD 或 Docker 构建)下,即使 SSH 配置正确,git 仍可能 fallback 到密码输入,导致 Composer 卡住。需禁用所有交互式凭据:
- 全局设置 git 不尝试密码认证:
git config --global core.sshCommand "ssh -o PreferredAuthentications=publickey" - 更彻底的方式:在执行 Composer 前临时设置环境变量(尤其适用于容器):
export GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -i /path/to/id_rsa"
- 注意:CI 环境中不要把私钥硬编码进命令行,应通过 secret 注入文件,并确保文件权限为
600(chmod 600 /path/to/id_rsa),否则 ssh 会拒绝读取
最常被忽略的一点:SSH 配置里的 Host 名必须和 composer.json 中 url 的主机部分完全一致——git@gitlab.example.com 和 git@gitlab.example.com:22 在 SSH config 中属于不同 Host,后者需要单独配置端口。稍有不匹配,密钥就不会被选用。







