composer不支持镜像代理转发gitlab私有包,必须显式声明type为vcs的仓库、url以.git结尾、认证通过auth.json配置且权限为600,包名与私有库composer.json中name字段逐字符一致。

Composer 本身不支持“镜像代理转发”——你不能让一个内网地址自动把请求转给 GitLab,再把响应原样返回。所谓“GitLab 私有依赖走镜像代理”,本质是两件事:配对认证 + 显式声明仓库类型,缺一不可。
为什么 composer config -g repo.packagist 对 GitLab 私有包完全无效
因为 repo.packagist 只控制元数据源(packages.json、provider-*.json),而 GitLab 私有包走的是 vcs 类型仓库,根本不会查这个配置。Composer 拉私有 Git 仓库时,直接调用 git clone 或 HTTP API,绕过所有 packagist 镜像逻辑。
- 你在全局设了
repo.packagist镜像,但require的包没在 packagist.org 上注册,Composer 就会去repositories里逐个找,跟镜像无关 - 如果
repositories里写的是"type": "git"或漏掉"type": "vcs",Composer 会静默跳过,报错却是模糊的Could not find package - GitLab 实例若启用了双因素(2FA)或 API 访问限制,
repo.packagist配置再正确也救不了拉取失败
auth.json 必须放对位置且权限严格
auth.json 不是可选配置,而是 GitLab 私有包能被识别的硬门槛。它必须位于用户主目录下的 ~/.composer/auth.json(Windows 是 %USERPROFILE%\AppData\Roaming\Composer\auth.json),且文件权限必须是 600。
- Token 必须带
read_api和read_repository权限;GitLab 15+ 还要求apiscope 才能访问 v4/projects 接口 - HTTPS 方式 URL 中必须含
.git后缀,否则 GitLab 返回 404;SSH 方式必须用git@gitlab.example.com:group/repo.git格式,不能混用 HTTPS 域名 - 别把 Token 写进
composer.json或用COMPOSER_AUTH环境变量——GitLab 不支持 bearer token 自动注入,只认auth.json里的http-basic结构
项目级 repositories 顺序和结构决定是否生效
私有仓库声明必须放在 composer.json 的 repositories 数组最前面,且 type 必须为 vcs。只要数组里有任意一个 "type": "composer" 条目(比如你误加了 packagist.org 回退源),私有仓库就可能被跳过。
- 正确示例:
{ "repositories": [ { "type": "vcs", "url": "https://oauth2:YOUR_TOKEN@gitlab.example.com/group/internal-package.git" } ], "require": { "group/internal-package": "dev-main" } } - 包名
group/internal-package必须与该仓库内composer.json中的"name"字段逐字符一致(包括大小写) - 分支名必须加
dev-前缀,如dev-main;标签则用v1.0.0,不能写1.0.0
所谓“代理转发”真正能落地的只有两种路径
如果你真想让 GitLab 请求经过中间层(比如审计、缓存、统一鉴权),就得自己搭服务——Composer 不提供这一层能力。
- 用
composer-proxy(Go 编写)可代理 packagist 元数据,但它不处理 Git 仓库,对 GitLab 私有包无效 - 要代理 Git 请求,得用 Nginx +
proxy_pass+ 自定义 auth header 注入,但 GitLab 的 API 路由复杂(如/api/v4/projects/:id/repository/archive.zip),简单反代极易 404 或返回空 ZIP - 更稳妥的做法是:在 CI/CD 流水线中提前
git clone --mirror到内网 Git 服务器(如 Gitea),再把repositories.url指向这个内网地址,由运维统一维护同步策略
最容易被忽略的一点:GitLab 私有包的 composer.json 里如果写了 "repositories" 字段,它会影响下游项目的解析行为——不是只影响自己,而是会污染整个依赖树的仓库查找顺序。











