ci中用composer_auth传凭证最常踩的坑是json格式错误,必须严格单行、小写键名、无换行空格,否则静默跳过认证;正确写法为composer_auth='{"http-basic":{"host":{"username":"ci","password":"xxx"}}}',推荐用jq生成并首步校验是否加载。

CI里用COMPOSER_AUTH传凭证,JSON格式错一个字符就静默失败
CI流水线里最常踩的坑是把凭证硬编码进脚本或拼接JSON字符串。COMPOSER_AUTH要求严格单行、小写键名、无换行、无多余空格,否则composer install会跳过认证,报“Package not found”而不是“Authentication failed”。
- 正确写法:
COMPOSER_AUTH='{"http-basic":{"packages.your-company.com":{"username":"ci","password":"xxx"}}}' - 绝对不要手写JSON——用
jq生成:echo '{"http-basic": {"'"$REPO_HOST"'": {"username": "'"$CI_USER"'", "password": "'"$CI_TOKEN"'"}}}' | jq -c - CI第一步加校验:
composer config --global --list | grep -q "http-basic" || (echo "MISSING AUTH CONFIG" >&2; exit 1) - 禁止在
composer.json或auth.json里写死密码,Git历史不可删
自签名证书仓库必须显式配options.ssl.cafile,全局cafile不顶用
私有仓库用自签名证书时,composer install报“SSL certificate problem”,不是网络问题,是Composer根本没读你本地的CA证书。它只认repositories里每个源单独声明的options.ssl.cafile路径。
- 路径必须是绝对路径,且在所有环境可访问:Docker容器内要提前
COPY证书,CI节点要确保路径存在 - 证书文件必须是PEM格式(Base64编码),含完整链(根CA + 中间CA),不能是
.crt二进制或.pfx - Windows下路径写成
C:/certs/internal-ca.pem或C:\certs\internal-ca.pem,单反斜杠会被PHP解析为转义 - 别设
secure-http=false——它不解决证书问题,只允许降级HTTP,对私有HTTPS源无效
Git类私有仓库优先走SSH,CI里预装密钥比Token更稳
用"type": "vcs"配私有Git仓库时,HTTPS+Token容易因Token权限变更、过期或CI缓存旧Token而失效;SSH密钥只要公钥在Git服务端有效,就一直可用。
- CI中提前注入私钥:
echo "$SSH_PRIVATE_KEY" | tr -d ' ' | ssh-add - > /dev/null,并确保ssh-agent已启动 -
composer.json里URL写成git@github.com:org/repo.git,别用https://开头 - Git服务端必须把该密钥加为Deploy Key(非用户SSH Key),避免权限过大
- 若必须用HTTPS,Token权限至少含
repo(GitHub)或read_repository(GitLab)
Satis静态仓库需启用GPG签名,客户端强制验证才防篡改
用Satis搭的私有仓库,如果没开签名,攻击者一旦劫持构建机或CDN,就能往packages.json里塞恶意包。签名不是可选项,是防供应链投毒的底线。
- Satis构建命令必须带
--sign:php bin/satis build satis.json web/ --sign - 项目里启用元数据验证:
composer config -g repo.packagist.org.allow_ssl_downgrade false - 确保PHP启用了
openssl扩展,否则签名验证直接跳过 - 服务端Nginx必须关掉
autoindex on,加location / { try_files $uri =404; }防目录遍历
配置生效与否,关键看三件事:凭证是否被composer config --global --list真正加载、证书路径是否在容器内真实可读、SSH密钥是否被ssh-add -l列出。任何一步断在中间,错误都藏得极深。











