Satis仅静态生成符合Composer协议的JSON+ZIP包集合,不代理实时包、不同步新版本、无Web界面;需手动构建、配置Git源、设type为library等,适合内网或审计严格场景。

直接用 satis 搭建私有 Composer 镜像源,不是“配置一下就能用”,而是得先理清它不解决什么:它不代理 packagist.org 的实时包,不自动同步新版本,也不提供 Web 界面上传或搜索功能。它只做一件事——静态生成一个符合 Composer repositories 协议的 JSON + ZIP 包集合,适合内网、审计严格或只用固定几个私有包的场景。
为什么不用 Toran Proxy 或 Private Packagist?
因为它们是商业/托管服务,需要 License 或网络连通性;而 satis 是纯 PHP 命令行工具,输出全是静态文件,扔进 Nginx/Apache 就能用,零运行时依赖,审计友好。
常见错误现象:satis build 报错 Could not find package xxx,往往是因为目标包没设 "minimum-stability": "stable",或 composer.json 里没声明 "type": "library" —— satis 默认只收录 type 为 library、metapackage、project 的包。
- 确保所有要镜像的私有包都已发布到 Git(如 GitLab 私有仓库),且
composer.json中有明确"name"(格式必须是vendor/name) -
satis.json中的"repositories"列表,写的是源地址(Git URL),不是你本地路径 - 别把
satis.json和项目composer.json混为一谈:前者定义“我要镜哪些包”,后者定义“我依赖哪些包”
satis.json 核心字段怎么写?
最小可用配置只需三块:name(镜像名)、homepage(镜像首页 URL,会影响生成的 packages.json 里包的 dist.url)、repositories(源列表)。其他都是可选。
容易踩的坑:"output-dir" 必须是 Web 可访问路径(比如 /var/www/satis),且 satis build 运行用户要有写权限;"require-all" 设为 true 会拉取所有分支/Tag,但若某分支 composer.json 缺失或语法错误,整个构建就中断。
{
"name": "My Private Repository",
"homepage": "https://satis.internal",
"repositories": [
{ "type": "vcs", "url": "https://git.internal/project-a" },
{ "type": "vcs", "url": "https://git.internal/project-b" }
],
"require-dependencies": true,
"archive": {
"directory": "dist",
"format": "zip",
"skip-dev": true
},
"output-dir": "/var/www/satis"
}
build 前必须确认的三件事
satis build 不是黑盒命令,它背后会调用 git clone、composer install、zip,任何一步失败都会卡住或静默跳过。
- 运行
satis的机器必须能git clone所有repositories地址(检查 SSH key / HTTPS token / GitLab CI token 是否生效) - 如果私有包依赖了外部包(如
monolog/monolog),satis默认不会拉取它们 —— 除非你在satis.json里显式"require"它们,或设"require-dependencies": true(推荐) - 生成的 ZIP 包默认放在
dist/下,但实际 URL 路径由"homepage"+"archive.directory"拼出,比如https://satis.internal/dist/vendor-name-package-name-zip-hash.zip,务必确保 Web Server 能正确路由到该目录
客户端怎么用这个镜像?
不是改 ~/.composer/config.json,而是项目级配置,避免污染全局。在项目根目录的 composer.json 里加 repositories,并设 packagist.org 为 false 关闭公共源:
{
"repositories": [
{ "type": "composer", "url": "https://satis.internal" },
{ "packagist.org": false }
],
"require": {
"internal/project-a": "^1.2"
}
}
注意:"type": "composer" 表示这是一个完整的 Composer 镜像源(含 packages.json),不是单个 VCS 仓库;如果漏掉 "packagist.org": false,Composer 仍会 fallback 到官方源,导致私有包被忽略或版本冲突。
最常被忽略的一点:每次更新私有包的 Git Tag 后,必须手动重新运行 satis build,然后清空客户端 ~/.composer/cache —— Composer 缓存 packages.json 默认 5 分钟,不清理可能拉到旧清单。










