satis build 成功但 composer install 仍连外网,根本原因是 Composer 未配置私有源:repositories 缺失或错误、packagist.org 禁用格式错误、URL 缺尾部 /、缓存未清;Web 服务器 MIME 类型与路径配置不当也会导致 404。

直接跑 satis build 不等于生产可用 —— 三件事没对齐,composer install 一定 fallback 到 packagist.org 或 404。
为什么本地 satis build 成功,但项目里还是连外网?
根本原因不是 Satis 没生成文件,而是 Composer 根本没去你建的私有源查包。它默认只认 packagist.org,除非你显式告诉它“别去、换这个地址”。常见失效场景:
- 项目
composer.json的repositories字段漏了,或写成{"type": "package", ...}(错类型) -
"packagist.org": false写成"packagist.org": "false"(字符串非布尔值) -
url值结尾没加/,比如写成"https://pkg.internal",Composer 会拼出https://pkg.internal/packages.json/packages.json - 没清 Composer 缓存:
composer clear-cache必须在改完配置后执行,否则旧缓存仍走公网
satis.json 生产环境必须校验的三个字段
缺一不可,且嵌套层级不能错。很多构建无声失败(packages.json 为空)就源于这里:
-
repositories:顶层数组,每个元素必须是完整对象,例如{"type": "vcs", "url": "https://git.internal/lib"};不能是字符串 URL,也不能塞进子字段里 -
require-all或require:二者只能选其一。"require-all": true适合镜像全部 tag/branch;若只要稳定版,用"require": {"vendor/package": "*"},且确保目标仓库composer.json中name全小写、无下划线 -
output-dir:强烈建议绝对路径,如"/var/www/satis"。相对路径在 CI 脚本中极易因工作目录变化导致 ZIP 文件生成失败或权限拒绝
Nginx/Apache 托管时最容易被忽略的配置点
Satis 不起服务,只吐静态文件。Web 服务器配置错一个字,composer install 就 404:
-
root必须精确指向output-dir目录本身(不是它的父目录),例如 Nginx 配置root /var/www/satis; - 访问
https://pkg.internal/packages.json必须返回 HTTP 200 +Content-Type: application/json;Nginx 需显式加types { application/json json; } -
dist/下 ZIP 文件路径由 Satis 自动生成(如dist/vendor-package/123abc.zip),Web 服务器要允许该路径被公开 GET,不能设deny all或 require 认证 - 若用 HTTP(非 HTTPS),客户端必须提前运行
composer config -g secure-http false,否则 Composer 主动拒绝连接
构建失败时先盯住这三行日志
别急着重装或换 PHP 版本,90% 的构建卡点在这几个地方:
-
Could not fetch https://api.github.com/...:GitHub API 限流(未配 Token)或企业防火墙拦截;加"github-protocols": ["https"]并确保GITHUB_TOKEN环境变量已设 -
Could not parse version constraint dev-main:目标 Git 仓库的composer.json里写了"version": "dev-main"—— 删掉该字段,让 Satis 从 Git Tag 自动推断版本 -
scanning packages... 0 packages:检查repositories中 URL 是否可 curl 通,且对应 Git 仓库根目录下存在合法composer.json(含正确name字段)
生产环境最常被绕过的环节是 Web 服务 MIME 类型和客户端缓存清理 —— 这两个点不验证,前面所有配置都白搭。


















