私有仓库必须在项目根目录composer.json的repositories字段声明,类型选composer或vcs;认证凭据仅通过auth.json(权限600)配置;VCS包版本依赖Git tag且须符合语义化格式;Satis需手动build更新packages.json。

私有仓库必须用 composer.json 的 repositories 字段声明
Composer 不会自动发现你本地或内网的私有包,必须显式告诉它“去哪找”。不配这个字段,composer require vendor/package 会直接报 Could not find package。
常见错误是只改了包自身的 composer.json,却忘了在项目根目录的 composer.json 里加 repositories。注意:这是项目级配置,不是全局或包级配置。
- 类型选
composer(推荐):指向一个支持packages.json的 HTTP 服务,比如 Satis 或 Private Packagist - 类型选
vcs(简单场景):直接写 Git 地址,如"type": "vcs", "url": "https://git.internal/project-a",但要求该 Git 服务支持 Composer 自动读取composer.json和 tag - 避免用
package类型硬编码版本——维护成本高,无法自动更新
auth.json 是访问私有源的唯一安全凭据载体
HTTP Basic Auth、Git SSH key、OAuth token 这些认证信息,绝不能写进 composer.json,否则会随代码提交泄露。Composer 只认用户家目录或项目根目录下的 auth.json 文件。
典型结构:
{
"http-basic": {
"repo.internal.com": {
"username": "deploy",
"password": "xxx"
}
},
"github-oauth": {
"github.com": "token_xxx"
}
}
注意点:
-
auth.json权限必须是600(Linux/macOS),否则 Composer 会忽略它并报Authentication failed - CI 环境中,别用
composer config --global写凭据——不同项目可能需要不同账号,应通过环境变量注入或挂载文件 - Git over HTTPS 需要
http-basic;SSH 方式则依赖系统 ssh-agent,无需auth.json
私有包的 version 必须对应 Git tag,且格式要合规
Composer 解析私有 VCS 包时,不看 composer.json 里的 version 字段,而是根据 Git tag 自动推导版本号。如果没打 tag,dev-main 或 dev-master 是唯一可用的“版本”。
常见翻车现场:
- 打了
v1.0,但没加前缀——正确应为v1.0.0或1.0.0;Composer 默认只识别语义化版本(MAJOR.MINOR.PATCH) - 用了
feature/xxx分支名当版本——Composer 不会把它当作稳定版,require时得写"dev-feature/xxx",且需"minimum-stability": "dev" - 修改了 tag 对应的 commit 后强制推送——Git 服务器缓存可能未刷新,Composer 仍拉旧内容,需清
composer clear-cache
Satis 静态仓库比纯 VCS 更可控,但生成逻辑容易被忽略
如果你需要统一管理多个私有包、控制可见性、提供搜索页或离线安装能力,Satis 是轻量首选。但它不是“开箱即用”的服务,核心动作是运行 satis build 生成静态 packages.json。
关键细节:
-
satis.json里repositories列出的是“源”,不是最终仓库地址;output-dir才是对外提供的 HTTP 根路径 - 每次更新私有包的 tag 后,必须重新
satis build,否则新版本不会出现在packages.json中 - 生成的
packages.json默认不包含 dev 分支,如需支持,得加"require-all": true并设"minimum-stability": "dev" - 别把
satis.json放在output-dir下——会被当成普通包索引,导致解析失败
私有仓库最难绷的不是搭建,是让所有开发者和 CI 环境对齐同一套版本来源、认证方式和缓存行为。少一个 auth.json 权限位,或一次忘记 satis build,就足够卡住整个依赖链。










