satis构建后404主因是web服务器未正确暴露静态文件:nginx root须精确指向output-dir,必须声明application/json mime类型,镜像url须以/结尾,dist下zip路径需可直连get,且selinux或权限常导致访问失败。

离线环境配本地私有源,核心不是“关网络”,而是让 Composer 完全不发起任何 HTTP 请求——所有 packages.json 和 .zip 文件必须已就位,且路径可被直接 GET 访问。Satis 是目前最稳的方案,但配置错一个斜杠、少一个 MIME 类型、权限没设对,都会导致 404 或静默 fallback 到 packagist.org。
为什么 Satis 构建完还是 404?
Satis 只是静态文件生成器,不启动服务。404 的真实原因几乎全是 Web 服务器暴露路径失败:
-
nginx root必须精确指向satis.json中output-dir,例如root /var/www/satis/web;,不能多一级或少一级 - 必须显式声明 JSON MIME 类型:
types { application/json json; },否则返回text/plain,Composer 拒绝解析 - 镜像 URL 必须以
/结尾:"url": "http://192.168.1.100/",少斜杠会拼成http://192.168.1.100packages.json -
dist/下 ZIP 路径要能直连 GET,例如http://192.168.1.100/dist/monolog/monolog/2.10.0/monolog-2.10.0.zip,SELinux 或chmod权限常锁死该路径
项目级 composer.json 怎么写才真正走本地源?
私有源必须写在你要装包的那个项目的根级 composer.json 里,不是 Satis 自己的配置文件,也不是包自己的 composer.json:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 类型必须是
"type": "composer",URL 是托管packages.json的根地址(含末尾/) - 必须加上
"packagist.org": false,且放在repositories数组里,不是嵌套在某个仓库对象内部 - 私有源必须放在
repositories数组第一位,Composer 按顺序查找,不会合并同名源 - 示例结构(注意顺序和字段位置):
{ "repositories": [ { "packagist.org": false }, { "type": "composer", "url": "http://192.168.1.100/" } ], "require": { "monolog/monolog": "^2.10" } }
怎么验证是否真走本地源?
别信 composer install 是否报错,要看实际请求路径:
- 运行
composer show monolog/monolog --verbose,检查输出中dist.url是否指向你的内网地址,而不是https://api.github.com或https://packagist.org - 用
curl -I http://192.168.1.100/packages.json确认能返回200 OK和Content-Type: application/json - 检查
vendor/下包的composer.lock里dist.url字段,它决定了下次 install 从哪拉 ZIP - 如果仍 fallback,大概率是
repositories数组顺序错了,或者"packagist.org": false写在了错误层级
最容易被忽略的是:Satis 构建时默认不下载 dev 分支的 ZIP,除非你在 satis.json 里显式设 "archive": { "skip-dev": false };而很多私有包只维护 main 或 develop 分支,没打 tag,不打开这个开关就根本进不了 dist/ 目录。










