必须显式声明私有仓库URL、禁用packagist.org、确保packages.json可访问且认证就绪,否则Composer会静默fallback到外网导致“Could not find package”。

要在内网或私有环境中让 Composer 安装包时从你搭建的代码仓库(如 Satis、Artifactory 或 packagist-mirror)拉取,而不是默认访问 packagist.org,必须显式声明仓库地址、禁用默认源、确保元数据可访问且认证就绪——漏掉任一环节都会导致 Could not find package 或静默 fallback 到外网。
确认仓库类型并生成有效元数据
先判断你搭的是哪类仓库:Satis 是静态索引,Artifactory 是代理型 Composer 仓库,packagist-mirror 是实时同步镜像。三者配置逻辑完全不同。
如果是 Satis,必须运行 php bin/satis build satis.json web/ 生成 packages.json 和 dist/ 归档;不执行这步,Nginx 下即使能访问目录也返回 404,Composer 会直接跳过该源。
如果是 Artifactory,必须在 Web UI 中创建 Package Type = composer 的 Local/Remote/Virtual 仓库,Generic 类型不被识别;Virtual 仓库还需手动勾选“Enable Default Deployment Repository”,否则 composer publish 拒绝上传。
如果是 packagist-mirror,需确保 Redis 队列服务正常、OSS 存储可写、Go 进程持续运行;它不依赖本地 packages.json 文件,但要求 /packages.json 接口返回 200 且内容为合法 JSON。
项目级 composer.json 配置 repositories
第一步:把自建仓库 URL 显式加进 repositories 数组最前面,type 必须为 "composer",不能是 "vcs" 或留空。
第二步:URL 必须以 斜杠 / 结尾,例如 "https://satis.internal.example.com/";少一个字符就会触发 404,Composer 不报错也不提示,直接 fallback。
第三步:必须在同一层级添加 "packagist.org": false,否则 Composer 仍优先查官方源,你的私有包永远不会被匹配——这是 90% 找不到包的根本原因。
正确示例:
{ "repositories": [ {"type": "composer", "url": "https://satis.internal.example.com/"} ], "packagist.org": false}
验证 packages.json 是否可被读取
打开浏览器或执行:curl -I https://satis.internal.example.com/packages.json。
必须返回 HTTP 200,且响应头包含 Content-Type: application/json;若返回 403、404 或重定向到登录页,Composer 会静默忽略该仓库,转而尝试 packagist.org。
如果用 Nginx,检查是否误加了 deny all 或未配置 index packages.json;如果用 Apache,确认 .htaccess 没屏蔽 JSON 文件。
全局认证配置(仅限需要账号密码的仓库)
方法一:Linux/macOS 下,在 ~/.composer/auth.json 写入:
{ "http-basic": { "satis.internal.example.com": { "username": "api", "password": "token-xxx" } }}
方法二:Windows 下,文件路径为 %APPDATA%\Composer\auth.json,内容结构相同。
注意:必须运行 chmod 600 ~/.composer/auth.json,权限大于 600(如 644)时 Composer 直接忽略该文件,不报任何错误。
执行安装并观察实际请求路径
运行 composer require acme/utils:dev-main -vvv,观察输出中是否出现 Downloading https://satis.internal.example.com/p2/acme/utils.json。
如果看到的是 Downloading https://packagist.org/p2/acme/utils.json,说明 "packagist.org": false 没生效或 repositories 位置写错;如果卡在 Reading composer.json of acme/utils (dev-main) 后无响应,大概率是 packages.json 不可达或 auth.json 权限不对。
这一步执行完后,Composer 会下载 dist 包、解压、生成 autoloader——整个流程结束。











