composer config -g repo.packagist 在局域网私有镜像中无效,因其仅替换 packages.json 元数据地址,不修改包的 dist.url 字段,后者仍指向 github 等外网地址,导致 zip 无法下载;真生效需确保所有 dist.url 指向内网可访问 http 路径,并正确配置 web 服务暴露静态文件。

直接改 composer config -g repo.packagist 在局域网里基本无效,它只换元数据地址,不接管 ZIP 包下载路径;真要跑通,必须让每个 dist.url 都指向你内网可直连的 HTTP 地址。
为什么 composer config -g repo.packagist 在局域网里静默失效
这条命令在公网镜像(如阿里云)下能凑合用,但在局域网私有源场景下几乎必然失败,原因很实在:
- 它只修改
packages.json的获取地址,完全不碰任何包的dist.url字段 -
dist.url仍来自原始源(比如https://github.com/monolog/monolog/releases/download/2.10.0/monolog-2.10.0.zip),局域网根本打不开 - 国内公开镜像(阿里云、腾讯云、USTC)也不托管 ZIP 文件,只缓存元数据
- 验证真实 ZIP 地址:运行
composer show monolog/monolog --verbose,看输出里的dist.url是否还指向 GitHub
项目级 composer.json 怎么写才真正走私有镜像
私有源必须写进你要装包的那个项目的根级 composer.json,不是 Satis 自己的配置文件,也不是包自己的 composer.json。漏掉任意一项,composer require acme/utils 就会报 Could not find package:
- 类型必须是
"type": "composer",URL 是托管packages.json的根地址,且末尾必须带/(例如"url": "http://nexus:8081/repository/composer-group/") -
"packagist.org": false必须显式写在repositories数组顶层,不是嵌套在某个仓库对象内部 - 私有源必须放在
repositories数组第一位,Composer 按顺序查找,不会合并同名包 - 如果已有其他仓库(比如私有
package定义),别手动覆盖整个数组,用composer config repo.packagist composer http://...追加更安全 - 改完立刻删掉
vendor/和composer.lock,否则旧 lock 文件里的哈希仍指向原始源,校验失败
Nginx 或 Nexus 暴露 ZIP 路径时容易踩的坑
镜像服务本身不“主动分发”,只是静态文件托管,路径和响应头稍有偏差就会 404 或被 Composer 拒收:
- Nginx 的
root必须精确指向 Satis 的output-dir的子目录(如root /var/www/satis/web;),不能多一层或少一层 - 必须显式声明 JSON MIME 类型:
types { application/json json; },否则packages.json返回text/plain,Composer 直接跳过 - 验证 ZIP 是否可直连:打开浏览器或
curl -I https://pkgs.internal/dist/monolog/monolog/2.10.0/xxx.zip,确认返回200且Content-Type: application/zip - 检查 SELinux 状态或文件权限:
ls -l /var/www/satis/web/dist/是否可被 Web 用户读取 - 没把
packages.json设为默认索引文件,访问根路径https://pkgs.internal/时服务器去找index.html,但 Satis 默认不生成这个文件
验证镜像是否真生效,别信 composer config -g 输出
composer config -g repo.packagist 只告诉你“你写了什么”,不等于 Composer 正在用它。真正生效要看实际网络请求:
- 跑一次真实操作:
composer clear-cache && composer require monolog/monolog -vvv - 在日志里搜索
Downloading,确认出现的是你的内网地址,比如https://pkgs.internal/packages.json或https://pkgs.internal/dist/monolog/monolog/2.10.0/xxx.zip - 如果看到
https://packagist.org/packages.json或https://github.com/...,说明镜像根本没走通 - 另外,
composer diagnose里的Repo packagist.org:行也会显示当前实际使用的 URL,比config -g更可靠
复杂点在于:镜像配置只是链条的第一环,ZIP 文件路径、Web 服务响应头、文件权限、SELinux、Nginx root 配置——任何一个环节断掉,都会表现为“404”或“could not find package”,但错误日志里往往不提示具体哪一环崩了。











