私有镜像源必须用 composer 2.2+ 的 repositories 数组格式:首项独立写 {"packagist.org": false},第二项起为私有镜像(含 "type": "composer" 和末尾带/的 url),否则元数据仍直连 packagist.org。

私有镜像源必须用 Composer 2.2+ 的 repositories 数组格式
Composer 2.2 起废弃了 repositories 对象写法(如 {"packagist": {...}}),改用严格数组结构,且必须显式禁用官方源。否则即使 URL 正确,元数据请求仍直连 packagist.org,私有镜像形同虚设。
正确写法要求:
-
{"packagist.org": false}必须是数组第一项,独立对象,不能合并到下一项 - 私有镜像条目必须是第二项或之后,
"type": "composer"不可省略 - URL 必须以
/结尾,否则请求路径拼接错误(如变成/packages.json) - 若已有其他私有 VCS 源(如 GitLab),需插在镜像条目之后,不能删掉首项
示例(项目级 composer.json):
"repositories": [
{"packagist.org": false},
{
"type": "composer",
"url": "https://your-private-mirror.com/composer/"
}
]
同步失败时先确认镜像服务是否真正响应
私有镜像配置后仍卡在 Loading composer repositories,大概率不是 Composer 配置问题,而是镜像服务本身未就绪。别急着改 composer.json,先人工验证端点:
- 用
curl -I https://your-private-mirror.com/composer/packages.json看是否返回200 OK且Content-Type: application/json - 检查响应头是否有
X-Content-Type-Options: nosniff或 CSP 限制,某些 Nginx/Cloudflare 配置会拦截 JSON 响应 - 确认镜像服务已启用
allow-plugins(如 Satis、Private Packagist),否则composer show可能只返回空列表 - 私有镜像若基于 Satis 构建,需确保
build命令已执行且生成了packages.json和完整 ZIP 包
私有镜像 + 全局配置混用会静默失效
全局配置(composer config -g repo.packagist)和项目级 repositories 数组共存时,Composer 优先读取项目级定义 —— 这是设计行为,不是 bug。但容易被忽略的是:全局配置中的 allow-fallback 设置对私有镜像无效,它只作用于 packagist.org fallback 逻辑。
常见陷阱:
- 误以为配了全局
repo.packagist.allow-fallback false就能强制走私有源,其实只要项目composer.json里有repositories数组,该设置完全不生效 - 私有镜像不可用时,Composer 不会 fallback 到全局镜像,而是直接报错
Could not find package,因为项目级配置已完全接管仓库发现流程 - 调试时用
composer install --no-cache -vvv,观察日志里实际请求的 URL 是不是你的私有地址,而非packagist.org或全局镜像
私有镜像认证凭据不能写进 composer.json
如果私有镜像需要 Basic Auth 或 OAuth Token(比如自建 Nexus 或 Artifactory),composer.json 里绝不能硬编码用户名密码。正确方式是通过 auth.json 管理:
- 在项目根目录创建
auth.json(或用户级~/.composer/auth.json),内容为:
{
"http-basic": {
"your-private-mirror.com": {
"username": "xxx",
"password": "yyy"
}
}
}
-
auth.json必须设为600权限(chmod 600 auth.json),否则 Composer 会拒绝读取 - CI 环境中,把凭据注入为环境变量(如
COMPOSER_AUTH),避免提交敏感信息 - 若用 GitHub Actions,推荐用
actions/setup-php的extensions参数自动注入,比手写auth.json更安全
最易被忽略的一点:私有镜像的 packages.json 必须包含完整元数据(含 dist 和 source 字段),否则即使认证通过,composer install 仍可能因无法解析 ZIP 下载地址而失败。











