Satis是Composer官方推荐的轻量级静态仓库生成器,通过将composer.json编译为packages.json和ZIP归档实现私有包分发,不运行HTTP服务、不依赖数据库、无运行时组件,仅需PHP环境与Web服务器即可部署。

直接用 Satis 就行,别碰 Artifactory 或 Nexus——它不提供服务、不依赖数据库、生成即静态文件,适合绝大多数 PHP 团队的私有包分发需求。
为什么选 Satis 而不是其他方案
Satis 是 Composer 官方推荐的轻量级静态仓库生成器,核心逻辑是“把 composer.json 编译成可被 composer install 直接拉取的 packages.json 和 ZIP 归档”,不跑 HTTP 服务、不连数据库、不处理实时请求。这意味着:
- 部署极简:只需一台能跑 PHP 的机器 + 一个 Web 服务器(Nginx/Apache)
- 无运行时依赖:不需要维护后台进程、队列或数据库连接
- 天然离线可用:生成的
web/目录整个拷走就能用 - 安全可控:所有包元数据和 dist 文件都由你完全掌控,不经过任何第三方
Artifactory/Nexus 虽然功能强,但配置复杂、容易因 type 选错(比如误选 generic)导致 Invalid repository type 报错;而 Satis 几乎只可能卡在 Git 权限或 URL 拼写上,排查路径清晰。
satis.json 最小可用配置怎么写
一个能跑通的 satis.json 必须包含三项:name、homepage、repositories,且 repositories 中每个源必须是 type: "vcs" 并指向真实可 git clone 的地址:
{
"name": "Internal Packages",
"homepage": "https://packages.internal",
"repositories": [
{
"type": "vcs",
"url": "https://git.internal/project-a.git"
}
],
"require-all": true
}
注意几个硬性要求:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
homepage必须是最终仓库访问的完整 URL(含协议),它会作为所有包dist.url的前缀 -
url值末尾必须带.git(HTTPS)或.git后缀(SSH),写成https://git.internal/project-a会报No valid composer.json was found - 如果只想要特定包,删掉
"require-all": true,改用"require": { "vendor/name": "*" },且该值必须和目标仓库根目录下composer.json中的name字段**完全一致** - 不要在
repositories里写packagist.org或其他 Composer 源——Satis 不代理动态源,只抓 VCS 仓库
构建失败常见原因和对应解法
执行 php bin/satis build satis.json web/ 报错,90% 都出在这三处:
-
Failed to clone https://git.internal/project-a.git:运行 Satis 的系统用户没配 Git 凭据。HTTPS 方式需提前执行git config --global credential.helper store并输一次密码;SSH 方式要确保~/.ssh/id_rsa.pub已加到 Git 服务端 -
Could not parse version constraint dev-main:目标仓库的composer.json里写了"version": "dev-main"——这个字段必须删掉,让 Composer 自动从 Git Tag 推断版本 - 生成的
web/packages.json为空或只有 1 个包:检查satis.json中repositories.url是否拼错,以及对应 Git 仓库根目录下是否存在合法的composer.json(含name和autoload)
另外,satis build 不支持增量更新,每次都是全量扫描。如果仓库多,建议用 php bin/satis build satis.json web/ vendor/package 指定包名来局部构建,避免重刷全部。
客户端项目怎么接入才不 fallback 到 packagist.org
项目级 composer.json 必须同时满足两个条件,否则 composer install 仍会静默回退到官方源:
- 在
repositories数组中显式添加私有源,且type为"composer",url以/结尾:{"type": "composer", "url": "https://packages.internal/"} - 在同一层级(非嵌套)声明
"packagist.org": false——漏掉这行,哪怕 URL 写对了,也会报Could not find package vendor/name
示例片段:
{
"repositories": [
{
"type": "composer",
"url": "https://packages.internal/"
}
],
"packagist.org": false,
"require": {
"vendor/name": "dev-main"
}
}
最后确认一点:生成的 web/ 目录必须能被 Web 服务器直接访问,且 curl -I https://packages.internal/packages.json 返回 200。如果 Nginx 返回 403/404,Composer 会直接放弃该源,不会报错,只会 fallback。

















