错误信息
fatal: unable to access 'https://git.example.com/team/app.git/': server verification failed: certificate signer not trusted. (CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none)
也可能输出为
- server verification failed: certificate signer not trusted. (CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none)
- server certificate verification failed. CAfile: none CRLfile: none
消息中的 URL 是你的远程仓库地址。较旧的 Debian 和 Ubuntu 版本(libcurl 7.x)会打印更短的“server certificate verification failed. CAfile: none CRLfile: none”,其中“CAfile: none”只表示没有显式配置 CA 文件,使用的是系统证书包。
含义
git 的 HTTPS 传输层(在 Debian 和 Ubuntu 上是基于 GnuTLS 构建的 libcurl)无法验证 Git 服务器的证书:证书链中没有任何一张证书能通向它所读取的证书包中的 CA。“certificate signer not trusted”是 GnuTLS 表示颁发者未知的说法;此时还根本没有检查你的凭证或仓库。
原因
使用公司证书的自托管 GitLab、Gitea 或 Bitbucket
常见自托管的 Git 服务器常常使用内部 CA 签发的证书。开发者的笔记本电脑通过设备管理获得了该根证书;Linux 容器、CI 运行器和 WSL 发行版通常没有。
Git 服务器没有发送中间证书
常见GitLab、Gitea 以及它们前面的反向代理经常只配置了叶子证书。浏览器会补上缺口,GnuTLS 则不会。
你和 Git 主机之间有一个执行 TLS 检查的代理
偶见如果从 github.com 或 gitlab.com 克隆只在公司网络中失败,说明流量被某个代理重新签名,而该代理的根证书不在本机的证书包中。
镜像中没有 CA 证书包
偶见装了 git 但没有 ca-certificates 的精简镜像,对任何 HTTPS 远程仓库都会失败。
修复方法
- 1.
查看 Git 服务器发送了哪些证书
如果只出现了叶子证书,就修复服务器。如果证书链终止于公司根证书或代理根证书,就在客户端上安装该根证书。
bash openssl s_client -connect git.example.com:443 -servername git.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' - 2.
只为某一个 Git 服务器信任 CA
http.<url>.sslCAInfo 把自定义 CA 限定在一个主机上,因此公共远程仓库继续使用系统证书包。GIT_SSL_CAINFO 则对单条命令或单个 CI 作业起同样的作用。
bash # Trust the company CA for this server only; other remotes keep the system bundle git config --global http."https://git.example.com/".sslCAInfo /etc/ssl/private-ca/corp-root-ca.pem git ls-remote https://git.example.com/team/app.git - 3.
把根证书添加到系统证书包
通过 update-ca-certificates 安装根证书,可以一步修复 git、curl、wget 和包管理器。在 Docker 镜像中,在 Dockerfile 里完成这一步;在 CI 中,则在运行器镜像里完成。
bash sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates # git, curl and wget read /etc/ssl/certs/ca-certificates.crt - 4.
服务器所有者:配置完整证书链
Git 服务器的 Web 前端使用的证书文件必须先包含叶子证书,后面依次跟上所有中间证书。
text # GitLab Omnibus (/etc/gitlab/gitlab.rb): the .crt file must contain leaf + intermediates nginx['ssl_certificate'] = "/etc/gitlab/ssl/git.example.com.crt" # then: sudo gitlab-ctl reconfigure - 5.
临时诊断:只对一条命令跳过验证
只对单条命令使用 -c http.sslVerify=false,可以确认问题只出在信任上。如果全局设置它,你的凭证和代码就会发送给任何能够拦截该连接的人。
bash # Diagnostic only, for one command: never set http.sslVerify=false globally git -c http.sslVerify=false ls-remote https://git.example.com/team/app.git
相关错误
fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificat…git over HTTPS with libcurl + OpenSSL (Git for Windows default, macOS Homebrew, Alpine, RHEL)fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificat…git over HTTPS with libcurl + OpenSSL (Git for Windows default, macOS Homebrew, Alpine, RHEL)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)ERROR: The certificate of 'api.example.com' is not trusted.GNU Wget built with GnuTLS (Debian, Ubuntu before 22.04 used it too)