必须用命令验证实际生效项:先运行composer config -g repo.packagist查全局配置,再执行composer config repo.packagist(不带-g)查项目级覆盖,最后检查项目composer.json中的repositories字段;输出为json对象则有效,纯url需升级格式,null或报错则无配置。

确认当前生效的自定义仓库配置在哪
自定义仓库(比如私有 Packagist、GitLab 私仓、Satis 服务)的配置可能分散在三个位置:全局配置、项目级 composer.json、或项目级 config.json。直接看文件容易漏,必须用命令验证实际生效项。
运行 composer config -g repo.packagist 查全局镜像;若返回空或报错,说明没设全局镜像源。再进项目目录运行 composer config repo.packagist(不带 -g),看是否覆盖了全局设置。最后检查项目 composer.json 的 repositories 字段——这才是最常被修改、也最容易被 git 忽略的位置。
- 输出是 JSON 对象(如
{"type":"composer","url":"https://my-private-repo.com"})→ 配置有效,可备份 - 输出是纯 URL 字符串(如
https://my-private-repo.com)→ 是旧版写法,composer install可能 fallback 到官方源,需先升级为对象格式再备份 - 字段值为
null或报错Could not find config file→ 当前无该配置,跳过
只备份 config.json 不够,必须连带 auth.json 和 keys/
自定义仓库若需认证(如 GitLab token、私有 Satis basic auth),凭证通常存在 auth.json,GPG 签名密钥则放在 keys/ 子目录。单独拷贝 config.json 后,在新环境执行 composer install 会卡在 401 或提示 “Package not found”,因为没凭据。
先用 composer config -g --list 确认真实路径(新版 Composer ≥2.0 默认是 ~/.config/composer/,旧版是 ~/.composer/),然后递归复制整个目录:
cp -r ~/.config/composer ~/backup/composer-global-$(date +%Y%m%d)
Windows 用户必须用 robocopy,资源管理器拖拽会丢权限和长路径文件。
-
auth.json里含敏感 token,备份后建议加密或限制读取权限(chmod 600) - 如果
keys/下有*.pub或*.key,缺一则composer verify失败 - 不要只复制
config.json,否则composer global require会因缺 auth 失败
项目级自定义仓库必须单独备份 composer.json
很多团队把私有包源写在项目 composer.json 的 repositories 数组里,这类配置不会出现在全局 config.json 中,git 提交时还容易被 .gitignore 误删(比如忽略所有 *.json)。迁移时只拷全局配置,项目照样拉不到私有包。
检查方式:grep -A 10 '"repositories"' composer.json。只要看到非空数组,就必须把这个 composer.json 文件纳入备份范围。
- 若项目使用
platform或config覆盖 PHP 版本、超时等参数,这些也一并备份 - 不要依赖
composer dump-autoload输出来判断——它不反映仓库配置 - 备份时顺便校验
composer.lock是否包含私有包条目:jq '.packages[] | select(.name | startswith("mycompany/"))' composer.lock
迁移后验证自定义仓库是否真正可用
还原配置后不能只跑 composer install 就算完。有些仓库配置看似加载成功,但实际请求时被 DNS、防火墙或 token 过期拦截,错误日志藏在 verbose 模式里。
用 composer show -p mycompany/package-name -vvv 强制触发一次完整解析流程,观察最后几行是否出现 Reading https://my-private-repo.com/p/mycompany/package-name.json 和 Downloading https://my-private-repo.com/dist/...。如果卡在 GET https://repo.packagist.org/...,说明 fallback 成功了,自定义源根本没生效。
- 常见失败点:URL 末尾少
/(如https://my-repo.com→ 应为https://my-repo.com/) - token 权限不足(GitLab 需
read_api,不是仅read_repository) - 新服务器时间偏差 >5 分钟,导致 JWT token 被拒绝
自定义仓库的可靠性不取决于配置是否存在,而取决于每次请求都能拿到 200 响应——这点很容易被静默忽略。











