必须在 composer.json 顶层显式设置 "packagist": false 并将私有源置于 repositories 数组首位、{"packagist": false} 置于末位,且私有源需含 "type": "composer" 和末尾斜杠的 URL,否则 Composer 仍会 fallback 到 packagist.org。

必须在项目 composer.json 中显式禁用 packagist.org,并声明私有源类型与 URL,否则 Composer 仍会 fallback 到官方源——这不是网络或权限问题,是配置结构没写对。
为什么加了私有源还是连 packagist.org?
Composer 不会因为你在 repositories 里写了私有地址就自动忽略官方源。它默认始终启用 packagist.org,除非你明确关掉。
-
"packagist": false必须放在composer.json顶层(和require同级),不能塞进repositories数组里 - 顺序很重要:私有源对象要写在前,
{"packagist": false}必须是repositories数组的最后一个元素 - 漏掉
"type": "composer"字段,Composer 直接跳过该条目,不报错也不生效 - URL 缺末尾斜杠(如
https://satis.internal而非https://satis.internal/)会导致请求变成/packages.json→ 404
如何正确配置项目级私有源并禁用默认源
以下是最小可用配置,直接复制到项目根目录 composer.json 中即可:
{
"packagist": false,
"require": {
"myorg/utils": "^2.1"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.mycompany.com/"
},
{
"packagist": false
}
]
}
关键点:
- 删掉旧
composer.lock,运行composer update --lock重生成,否则 lock 文件里还留着 packagist.org 的记录 - 不要用
composer config repositories.xxx去改这个——它只适合添加临时源,不适用于禁用逻辑 - 私有源服务器必须已同步好所有依赖包,包括嵌套依赖;
"packagist": false后 Composer 不会自动补全缺失包
团队共享时最容易被忽略的兼容性陷阱
多人协作下,哪怕配置写对了,也常因环境差异失效:
- 本地开发用 WSL,但 CI 是纯 Linux —— 若私有源用了 HTTP Basic Auth,
auth.json路径和权限在不同系统上表现不一致 - Satis 或 Private Packagist 镜像未开启
providers-api,导致 Composer 在查包时 fallback 到官方源(看似配置生效,实则静默绕过) - 某成员手动执行过
composer config --global repo.packagist https://packagist.org,全局配置会干扰项目级"packagist": false的判断逻辑 - 私有源返回的
packages.json中缺少dist字段或 ZIP 包不可达,Composer 会退回到 VCS 模式拉 Git,而 Git 访问又可能被 SSH key 或 OAuth 拦住
真正起效的限制,不是靠“不让它连”,而是靠“让它连了也找不到”——所以私有源的完整性比配置本身更关键。一旦发现某个包仍从 packagist.org 下载,先打开 https://packages.mycompany.com/packages.json 手动确认该包是否存在、dist URL 是否可访问,再回头检查 JSON 结构是否合法。


















