Satis 不是私有 Packagist,仅生成静态 JSON 和 ZIP 包,不支持实时依赖解析、搜索、Web UI 或用户注册;适合已知包列表、发布节奏稳定、安全要求高、不想运维 PHP 服务的团队。

直接说结论:Satis 不是私有 Packagist,它只生成静态 JSON 和 ZIP 包,不支持实时依赖解析、搜索、Web UI 或用户注册——适合已知包列表、发布节奏稳定、安全要求高、不想运维 PHP 服务的团队。
为什么 Satis 生成的源无法被 composer install 正确识别
常见现象是执行 composer install 报错:Could not find package xxx at any version,或提示 Skipping branch alias ... 后跳过所有包。根本原因是 Satis 默认只导出 dist(ZIP)形式,但未正确配置 require 中的版本约束与 repositories 的 type 匹配。
- 确保
composer.json中私有源 type 必须为"type": "composer",不是package或artifact - Satis 配置中必须显式启用
"archive": {"format": "zip", "skip-dev": true},否则不生成 dist 信息 - 每个私有包的
composer.json必须含"version"字段(tag 推送时可省略,但 Satis 构建时需能推断;建议统一打 Git tag) - 运行
php bin/satis build satis.json web/后,检查生成的web/packages.json是否包含目标包名及有效versions数组
satis.json 关键字段怎么写才不出错
一份易维护、少踩坑的最小可行配置要覆盖来源、归档、过滤和安全性三块:
-
"name"和"homepage"只是元信息,不影响功能,但缺失会导致某些镜像工具报 warning -
"repositories"列表里每个项目必须用"type": "vcs",且 URL 指向 Git 仓库(如"https://git.example.com/internal/logger"),不能是 ZIP 或本地路径 -
"require-all": true简单粗暴,但若某私有包依赖另一个未纳入 Satis 的内部包,会构建失败;更稳的方式是"require": {"vendor/package": "*"} -
"archive": {"prefix-url": "https://satis.example.com/dist"}必须和 Web 服务器实际可访问的 ZIP 路径一致,否则 Composer 下载 dist 时 404 - 加
"output-dir": "web/"显式指定输出目录,避免默认写到output/导致 Nginx 配置错位
Nginx 如何配置才能让 Composer 正常下载 ZIP 和 packages.json
Satis 生成的是纯静态文件,但 Composer 对 MIME 类型和 HTTP 头敏感。Nginx 错误配置会导致 packages.json 返回 200 但内容为空,或 ZIP 下载后校验失败。
- 必须设置
location / { try_files $uri $uri/ /index.html; },否则访问/packages.json会 404(因无后缀) - 显式添加
types { application/json json; application/zip zip; },否则某些旧版 Composer 会拒绝解析packages.json - ZIP 文件需支持
Accept-Ranges,在 location 块中加add_header Accept-Ranges bytes;,否则大包下载中断后无法续传 - 不要开启
gzip_static on并放任 Satis 生成 .gz 文件——Satis 不自动压缩,手动压缩后需同步更新packages.json中的dist.shasum和dist.url
真正麻烦的从来不是搭建,而是当某天开发提交了一个没打 tag 的分支、CI 忘记触发 Satis 构建、或者某人把 composer.json 里的 version 写成 dev-master 却期望它出现在 Satis 源里——这些情况 Satis 都不会报错,只会安静地漏掉包。










