satis 搭建私有 composer 仓库需手动构建、正确配置 web 服务与 mime 类型、显式声明 require 包而非 require-all、url 末尾加斜杠、避免与 artifactory/nexus 重复使用,并在 ci 中校验 autoload。

直接用 Satis 搭私有 Composer 仓库,不是不行,但容易卡在「包不更新」「权限失控」「镜像同步失败」这三处——核心问题不在配置本身,而在 satis.json 的构建逻辑和 Web 服务的触发时机。
为什么 satis build 总是不生效?
Satis 不是常驻服务,它只生成静态文件;每次修改 satis.json 后必须手动运行 php bin/satis build,且输出目录需被 Web 服务器(如 Nginx)正确映射到可访问路径。常见错误是把 build 输出放到 /var/www/html 下却忘了设好 index.html 和 packages.json 的 MIME 类型,导致 Composer 报 Unable to load package list。
- 确保 build 命令指定输出目录与 Web 根目录一致:
php bin/satis build satis.json /var/www/satis - Nginx 需显式支持 JSON:在 server 块中加
add_header Content-Type application/json;(仅对.json文件) - 不要用
php -S跑开发服务器——它不支持 Composer 所需的 HTTP 状态码和重定向行为
satis.json 中 repositories 和 require-all 怎么配才不漏包?
repositories 列的是你「想收录」的源,require-all 决定「实际打包哪些」。若设为 true,Satis 会尝试解析所有源的 composer.json 并合并依赖树,极易因某一个私有包缺失 dist 或 source 字段而中断整个 build。更稳的做法是显式 require 版本约束。
- 避免
"require-all": true,改用"require": { "vendor/package-a": "dev-main", "vendor/package-b": "^2.1" } - 每个
repository必须含type(推荐vcs)和可访问的url,GitLab 私有项目要带 token:"url": "https://token:x-oauth-basic@gitlab.example.com/group/repo.git" - 若包未打 Git tag,Satis 默认跳过 —— 加
"minimum-stability": "dev"并确认branch-alias或dev-main分支存在
如何让开发者不用改 composer.json 就能用私服?
全局配置 composer config -g repos.packagist.org false 会禁用 Packagist,但风险高;更安全的是用 composer config --global repos.my-private-repo composer https://satis.example.com。注意:这个 URL 必须以 / 结尾,否则 Composer 请求 packages.json 时会拼成 https://satis.example.compackages.json(少斜杠)。
- 验证是否生效:
composer config --global repo.my-private-repo应返回完整 URL - 若公司已用 Artifactory 或 Nexus,别硬套 Satis —— 它们原生支持 Composer repo 类型,且自动处理 auth、proxy、缓存,Satis 在这类环境里只是个冗余层
- CI/CD 中触发 build 前,先
git fetch --all --tags,否则新 tag 不会被 Satis 发现
真正麻烦的从来不是搭建,而是当某个团队悄悄把私有包的 composer.json 里 autoload 改成 PSR-4 但没更新命名空间,结果全量 build 后只有他们本地能装——这种问题不会报错,只会让其他人 composer install 后发现类找不到。Satis 不校验 autoload 正确性,得靠 pre-build 的 CI 检查兜底。











