satis 能用,但必须手动 build、必须配对 web 服务、必须显式 require 包名,否则包会“消失”或更新失败——它不是开箱即用的镜像服务,而是静态 json 生成器。

直接说结论:Satis 能用,但必须手动 build、必须配对 Web 服务、必须显式 require 包名,否则包会“消失”或更新失败——它不是开箱即用的镜像服务,而是静态 JSON 生成器。
为什么 satis build 后 composer install 找不到私有包
根本原因不是网络或权限,而是 Composer 客户端压根没去你部署的地址查包。satis 只生成 packages.json,不提供 HTTP 接口;你得用 Nginx/Apache 把输出目录(比如 web/)跑成一个可访问的域名,且 URL 必须以 / 结尾。
- 错误示例:
"url": "https://mirrors.example.com/satis"→ Composer 会请求https://mirrors.example.com/satis/packages.json(404) - 正确写法:
"url": "https://mirrors.example.com/satis/"→ 实际请求https://mirrors.example.com/satis//packages.json(Nginx 自动归一化) - 项目级配置必须写在项目根目录的
composer.json的repositories字段里,不是包自己的composer.json - 全局配置(
composer config -g repositories.xxx)只影响当前用户,CI 环境里默认不生效
satis.json 里 require-all 和 require 的实际区别
require-all: true 表面省事,实则埋雷:它会把所有仓库的所有分支、所有 tag 全部拉进 packages.json,文件体积暴涨,Composer 加载时容易内存溢出或超时;更糟的是,它会把 dev-* 分支也当版本暴露,导致 composer update 拉到不稳定代码。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 推荐写法:
"require": { "acme/utils": "^2.1", "acme/logging": "1.0.0" }—— 只收录明确声明的包和版本 - 不要用通配符:
"acme/*": "*"不被 Satis 支持,静默忽略 - 如果包尚未打 tag,
dev-main是唯一可用版本,但 require 时必须加"minimum-stability": "dev"到项目composer.json - archive 配置决定是否生成 ZIP:
"archive": { "directory": "dist", "format": "zip" }缺失时,composer install --prefer-dist会退回到 clone Git 仓库
私有 Git 仓库认证失败的三个关键点
Satis 构建时需要 clone 私有仓库,失败不会报错,只会跳过该包——结果就是 packages.json 里压根没有这个包,但你完全不知道。
- SSH 方式:确保运行
satis build的系统用户(如www-data)的~/.ssh/下有对应私钥,且ssh-agent已加载、known_hosts已记录主机指纹 - HTTPS + Token 方式:在
satis.json的repositories里写完整带 token 的 URL,例如"https://token:x-oauth-basic@github.com/acme/private.git" - 绝对不要把凭据写进
composer.json或satis.json—— 这些文件常进 Git,敏感信息立刻泄露 - 验证方式:手动用构建用户身份执行
git clone命令,看是否能成功拉下代码
为什么 composer update 很慢,甚至卡死
不是网络差,是 packages.json 太大。Satis 默认把每个包的全部历史版本元数据塞进一个 JSON 文件,100 个包 × 平均 15 个版本 = 几 MB 的 JSON,Composer 解析时吃光内存或触发 PHP max_execution_time。
- 立即检查:
curl -I https://mirrors.example.com/satis/packages.json看响应头Content-Length是否超过 2MB - 缩小体积:去掉
require-all,改用精确require;禁用不需要的分支("no-api": true在 repository 配置里) - 启用 Gzip:Nginx 配置中打开
gzip on;和gzip_types application/json;,可压缩 70% 以上体积 - 别信“自动更新”:Satis 没有 webhook 或实时同步,必须配定时任务(如
crontab)定期satis build,否则新 tag 永远不会出现在镜像里
最常被忽略的一点:Satis 生成的只是静态文件,它的健壮性完全依赖你 Web 服务器的 MIME 类型配置。Nginx 必须把 .json 响应为 application/json,否则 Composer 会解析失败并静默降级到 Packagist;Apache 同理,要确认 AddType application/json .json 已启用。










