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

直接说结论:Satis 不是服务,它只生成静态文件;你配错 repositories 位置、漏掉 "packagist.org": false 或 Web 服务器没托管好 packages.json,composer install 就会报 404 或 “Could not fetch”。
为什么 composer update 报 Could not fetch packages.json
这不是 Satis 没跑起来,而是 Composer 根本没连上你生成的 JSON 文件。常见原因有三个:
-
curl https://your-satis/repo/packages.json能通,但 Composer 不行?检查 Nginx/Apache 是否把packages.json设为默认索引(比如加index packages.json;),或路径是否对齐——satis.json里output-dir是/var/www/satis,那 URL 就必须是https://satis.example.com/packages.json,不能多出/repo/这一级 - Web 服务器返回 200 但内容是 HTML(比如 Nginx 默认页)?说明请求没落到
packages.json,而是被路由到了根目录的index.html,删掉或重命名它 - HTTPS 私有源没配
"secure-http": false?如果用的是自签名证书或 HTTP 内网地址,得在项目级或全局composer config里设这个开关,否则 Composer 直接拒绝连接
怎么写一个能被识别的 satis.json
核心字段只有三个:name、homepage、repositories。其他都是可选,但漏掉前两者会导致 Composer 加载失败。
-
name和homepage必须都有,且homepage必须是完整 URL(如https://packages.internal),它决定了所有包的dist.url前缀 -
repositories是顶层数组,不是require的子项——放错层级整个配置会被忽略 - 想只收录稳定版?别用
"require-all": true,改用"require": { "vendor/package": "*" },并确保目标仓库打了合规 tag(v1.2.0或1.2.0),否则 Satis 会跳过 - 私有 Git 地址用 SSH?确保运行
satis build的用户已配置好ssh-agent或~/.ssh/config;用 HTTPS?提前git config --global credential.helper store并输一次密码
客户端 composer.json 怎么正确接入私有源
不是加个 URL 就完事。顺序、类型、开关三者缺一不可。
-
repositories必须放在项目根目录composer.json的顶层,且type显式写成"composer"——别依赖默认值,旧版 Composer 可能不认 - 私有源 URL 必须和
satis.json里的homepage完全一致,包括末尾斜杠(https://packages.internal/≠https://packages.internal) - 必须加
"packagist.org": false,否则同名包可能从官方源拉取,导致版本冲突或安装失败 - 改完配置后,先
composer clear-cache,再composer install——缓存里可能还存着旧的元数据
build 出来 packages.json 为空或跳过包
Satis 不报错,但 packages.json 里没包,基本卡在 Git 层。
- 运行
satis build的用户没有 Git 权限?检查git clone是否能手动成功,特别是 SSH key 是否加载、HTTPS 凭据是否缓存 - 目标仓库根目录下没有
composer.json?Satis 会直接跳过,不提示 - Git tag 格式非法?比如写了
dev-main、feature/login或v1.2(缺 PATCH 位),Satis 默认只收vX.Y.Z或X.Y.Z - 用了
"require-all": true却没打任何 tag?那只会生成dev-master类版本,而minimum-stability默认是stable,结果就是“看不见”
最易被忽略的点:Satis 生成的 ZIP 包路径由 archive.prefix-url 和 archive.directory 共同决定,Nginx 必须能直接通过 HTTP 访问到这些 ZIP 文件,否则 dist 回退到 source 时会失败——这问题往往在上线后才暴露,因为本地 composer install 可能走的是缓存或 source 模式。











