satis必须生成静态文件并由内网web服务托管,因它不运行服务仅输出packages.json和dist/zip;客户端需显式声明私有源、禁用packagist.org、配置正确url结尾及mime类型,否则仍回退外网下载。

必须用 Satis 生成静态文件 + 内网 Web 服务托管,不能依赖任何在线服务或动态后端。Satis 本身不监听端口、不运行进程,只输出 packages.json 和 dist/ 下的 ZIP,所有访问都靠 Nginx/Apache 直接提供 HTTP GET。
为什么不能只改 composer config -g repo.packagist
这个命令只替换元数据入口(即 packages.json 的下载地址),但每个包的 ZIP 文件仍从原始 dist.url 下载——比如 https://github.com/monolog/monolog/releases/download/2.10.0/monolog-2.10.0.zip。局域网根本打不开 GitHub,而国内镜像(阿里云、USTC)也不托管 ZIP,只缓存 JSON 元数据。
验证真实 ZIP 地址:运行 composer show monolog/monolog --verbose,看 dist.url 字段。别信“换源就完事”,必须让所有 ZIP 都能通过内网 HTTP 直连 GET 到。
Nginx 必须精确暴露 Satis 输出目录并声明 MIME 类型
Satis 不是服务,只是静态文件生成器。404 不是网络不通,是 Web 服务没暴露对路。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
root必须精确指向satis.json中output-dir的路径,例如root /var/www/satis/web; - 必须显式声明 JSON MIME 类型:
types { application/json json; },否则返回text/plain,Composer 拒收 - 镜像 URL 必须以
/结尾:"url": "https://pkgs.internal/",少一个斜杠会拼成https://pkgs.internalpackages.json - 检查
dist/下 ZIP 路径是否可直连 GET,例如https://pkgs.internal/dist/monolog/monolog/2.10.0/xxx.zip,SELinux 或文件权限常锁死该路径
项目级 composer.json 的写法才是生效关键
私有源必须写在你要装包的那个项目的根级 composer.json 里,不是 Satis 自己的配置文件,也不是包自己的 composer.json。
根本原因是未显式禁用 packagist.org,默认源优先导致私有包不被匹配;必须在 repositories 数组后、与 require 同级的位置添加 "packagist.org": false:
{
"repositories": [
{
"type": "composer",
"url": "https://pkgs.internal/"
}
],
"packagist.org": false,
"require": {
"monolog/monolog": "^2.10"
}
}
漏掉 "packagist.org": false 就会报 Could not find package vendor/name,即使该包 100% 存在;URL 末尾的 / 也不能省,少一个就 404。
最关键的细节往往藏在最底层:ZIP 文件路径是否真能被 curl 直连、Nginx 是否真的返回 application/json、packagist.org 是否被显式关掉——这三处任一出错,都会让整个私有源静默 fallback 到外网,且无明确错误提示。










