Satis不是服务,只是静态文件生成器;配错repositories位置、未禁用packagist.org或Web服务器未正确托管packages.json,composer install就会卡在“Loading composer repositories”或报Could not fetch。

直接说结论:Satis 不是服务,只是个静态文件生成器;你配错 repositories 位置、漏关 packagist.org、Web 服务器没正确托管 packages.json,composer install 就会卡在 “Loading composer repositories” 或报 Could not fetch。
为什么 satis build 跑完还是连不上?
Satis 本身不监听端口、不启动进程,它只把元数据写成 packages.json 和一堆 ZIP 包丢进输出目录。你看到的“私服”其实是 Nginx/Apache 在提供服务——而它很可能根本没把请求路由到那个 JSON 文件上。
- 用
curl -I https://your-satis.example.com/packages.json检查:返回 404?说明路径不对;返回 200 但Content-Type是text/html?说明 Nginx 把请求 fallback 到了默认页,不是packages.json -
satis.json里"output-dir": "web",那 Web 根目录就必须是/var/www/html/web,而不是/var/www/html—— 否则 URL 少了一级路径 - Nginx 必须显式支持 JSON:
add_header Content-Type application/json;加在location ~ \.json$块里,不能只靠 MIME 类型自动推断 - 别用
php -S跑开发服务器:它不返回标准 HTTP 状态码,Composer 会静默失败
satis.json 的 repositories 和 require 怎么配才不崩?
repositories 是你要“扫描”的 Git 地址列表,require(或 require-all)才是决定“哪些包真被收录”的开关。很多人一上来就设 "require-all": true,结果 build 卡死——因为某个私有仓库没打 tag,或者 composer.json 缺 dist 字段。
- 优先用显式
require:"require": { "vendor/internal-api": "dev-main", "vendor/utils": "^3.2" },避免依赖树爆炸 - 每个
repositories项必须是顶层数组,不是嵌套在require下面;type推荐"vcs",url要带认证(如https://token:x-oauth-basic@gitlab.internal/group/repo.git) - Git 仓库没打语义化 tag(如
v1.0.0)?Satis 默认跳过。加"minimum-stability": "dev"并确认dev-main分支存在 -
homepage字段必须是完整 HTTPS URL,且末尾带斜杠:"https://packages.internal/"—— 少这个/,Composer 请求时会拼成https://packages.internalpackages.json
客户端 composer.json 怎么接入才不 fallback 到公网?
不是加个 URL 就完事。Composer 默认仍会尝试回退到 packagist.org,哪怕你只配了一个私有源。
-
repositories必须放在项目根目录composer.json的顶层,且type显式写"composer",不要省略 - 必须禁用默认源:
composer config --global repo.packagist false(全局)或composer config repo.packagist false(项目级) - 私有源 URL 必须和
satis.json中的homepage完全一致,包括协议、域名、端口、路径、末尾斜杠 - 内网用自签名证书?PHP 的
openssl.cafile必须包含你的 CA 根证书,否则 cURL 层就失败,composer update -v会卡在Downloading https://...无提示
CI 自动构建时容易忽略的三个硬伤
手动跑一次 satis build 很简单,但 CI 流水线里稍不注意就会导致包永远不更新、权限失控、甚至泄露凭据。
- Git token 写进
satis.json?绝对不行。应通过 CI secrets 注入环境变量,再在脚本里动态替换 URL:"url": "https://${GIT_TOKEN}@gitlab.internal/group/repo.git" - build 输出目录权限错误:Nginx 用户(如
www-data)必须有读取packages.json和 ZIP 包的权限,chmod -R 755 web/是底线,别用777 - 没校验 autoload:CI 最后一步应运行
composer validate --no-check-publish+composer dump-autoload -d web/(如果 Satis 配了 autoloader),否则上线后可能Class not found
真正卡住人的从来不是 build 命令本身,而是 Web 服务怎么把 packages.json 稳稳地、带正确 header 地交到 Composer 手里——这点一旦出错,所有后续调试都是在绕弯子。











