如何在Composer中配置SSH密钥以访问私有GitLab/Bitbucket仓库?

12次阅读

composer 依赖 gitssh 配置访问私有仓库,需确保 SSH 密钥正确配置、Git 未被 insteadOf 规则干扰、仓库 URL 使用 git@ 格式且权限合规。

如何在Composer中配置SSH密钥以访问私有GitLab/Bitbucket仓库?

Composer 默认用 https 克隆私有仓库,但 gitlab/Bitbucket 的私有项目若启用了 2FA 或禁用了密码认证(如 Bitbucket 已全面停用账户密码),就必须改用 SSH。关键不是“配 Composer”,而是让 git 命令本身能走 SSH 访问你的私有仓库,Composer 只是调用它。

确认 SSH 密钥已生成并添加到 Git 托管平台

Composer 不处理密钥管理,它完全依赖系统级的 git 行为。先确保:

  • 本地已有可用的 SSH 密钥(如 ~/.ssh/id_rsa~/.ssh/id_ed25519),且未设置密码(或已用 ssh-agent 加载)
  • 公钥(id_rsa.pubid_ed25519.pub)已完整复制并粘贴到 GitLab 的 Settings → SSH Keys 或 Bitbucket 的 Personal settings → SSH keys
  • 在终端执行 ssh -T git@gitlab.com(或 git@bitbucket.org)返回欢迎信息,而非权限拒绝

强制 Composer 使用 SSH URL 而非 HTTPS

即使你 composer.json 里写的是 HTTPS 地址(如 "vendor/package": "dev-main"),Composer 仍可能尝试用 HTTPS 克隆——除非你明确告诉它该包的源必须走 SSH。做法是配置 repositories 并指定 url 为 SSH 格式:

{     "repositories": [         {             "type": "vcs",             "url": "git@gitlab.com:your-group/your-private-package.git"         }     ],     "require": {         "your-group/your-private-package": "dev-main"     } }

注意:url 必须是完整 SSH URL(git@host:path.git),不能是 https://,也不能漏掉 .git 后缀;包名(your-group/your-private-package)必须与仓库的 name 字段或自动推断名一致,否则 Composer 找不到匹配源。

避免因 Git 配置导致 SSH 失效

常见坑:全局 Git 配置中设置了 insteadOf 规则,把所有 git@ 强制转成 HTTPS:

[url "https://"]     insteadOf = git@

这会让 git clone git@gitlab.com:xxx 实际走 HTTPS,直接失败。检查并删除这类规则:

  • 运行 git config --global --get-regexp insteadOf 查看是否有干扰项
  • 若有,用 git config --global --unset url."https://".insteadOf 清除
  • 仅对特定域名做重写才安全,例如只让 github 的 SSH 自动转 HTTPS(极少需要)

私有子模块或嵌套依赖也走 SSH?

如果私有包自身含有 .gitmodules 或依赖其他私有仓库,那些子依赖不会自动继承父项目的 SSH 配置。你必须确保:

  • 子模块的 URL 在其 .gitmodules 文件里也是 git@ 开头(而非 https://
  • 或在项目根目录运行 git submodule sync --recursive 同步后,手动修正子模块的远程地址:git -C vendor/your-package submodule set-url --all git@gitlab.com:subgroup/subpackage.git
  • Composer 不解析或改写子模块 URL,这是纯 Git 层行为

最易忽略的一点:SSH 密钥权限必须是 600chmod 600 ~/.ssh/id_*),且 ~/.ssh 目录不能被组或他人写入(chmod 700 ~/.ssh),OpenSSH 在严格模式下会直接拒用密钥,错误常表现为 Permission denied (publickey) 却不提示具体原因。

text=ZqhQzanResources