# curl: (77) error setting certificate verify locations 修复

> curl 报错 77 表示读不到 CA 证书文件或目录：没装 ca-certificates、CURL_CA_BUNDLE 或 --cacert 路径错误、文件权限不对。和网站证书无关。

Source: https://ssl.sh/zh/errors/curl-77-error-setting-certificate-verify-locations/
Last updated: 2026-11-10

**`curl: (77)` 的意思是：curl 打不开或解析不了它被指定使用的 CA 证书包，因此无法验证任何服务器。** 报错里写明了 `CAfile` 和 `CApath`，其中一个不存在、是空的、没有读权限，或者被环境变量、命令行选项指到了错误的位置。

## 快速修复

只要让 curl 指向一个存在、可读的 CA 证书包，报错就会消失。先检查报错里的路径，以及有没有东西覆盖了它：

```bash
ls -l /etc/ssl/certs/ca-certificates.crt
env | grep -E 'CURL_CA_BUNDLE|SSL_CERT_FILE|SSL_CERT_DIR'
curl -V
```

- **文件不存在：** 安装 CA 证书包（见下文）。
- **环境变量指向不存在的文件：** `unset CURL_CA_BUNDLE SSL_CERT_FILE`，并从 shell 配置、CI 设置或 Dockerfile 里删掉它。
- **文件存在：** 检查权限和内容，`head -1` 应该输出 `-----BEGIN CERTIFICATE-----`。

## 原因

最常见的原因是精简镜像没装 CA 证书包，其次是选项或环境变量给了错误路径。

### 1. 没装 CA 证书包

精简容器镜像（Debian slim、Alpine、基于 scratch 的镜像）经常没有 `ca-certificates`（系统的 [CA 证书包](https://ssl.sh/zh/glossary/ca-bundle/)）。

- **确认：** 报错里的路径不存在。
- **修复：**

```bash
apt-get update && apt-get install -y ca-certificates   # Debian/Ubuntu
apk add --no-cache ca-certificates                       # Alpine
dnf install -y ca-certificates                           # RHEL/Fedora/Rocky
```

国内构建镜像时，先把软件源换成阿里云、清华、中科大等国内镜像，再安装，速度会快很多。

### 2. 选项或环境变量给了错误路径

`--cacert`、`--capath`、`CURL_CA_BUNDLE`、`SSL_CERT_FILE`，或者 `~/.curlrc` 里的 `cacert` 行，指向的文件被移走了或者不存在（比如从别的发行版文档里抄来的路径）。

- **确认：** 报错里的 CAfile 和你的发行版默认路径不一样。
- **修复：** 改正或删除这个设置。发行版默认路径：Debian、Ubuntu、Alpine 是 `/etc/ssl/certs/ca-certificates.crt`，CentOS/RHEL 系是 `/etc/pki/tls/certs/ca-bundle.crt`。

### 3. 权限或 SELinux

- **确认：** 文件存在，但 `sudo -u www-data cat /路径/文件` 失败，或者审计日志里有 SELinux 拒绝记录。
- **修复：** CA 证书包本来就是公开数据，设为所有人可读（`chmod 644`），用 `restorecon` 恢复标签。

### 4. curl 是按别的系统路径编译的

从别的系统复制过来的 curl 二进制、静态编译版，内置的是编译机上的 CA 路径。

- **确认：** `curl -v https://example.com 2>&1 | grep CAfile` 显示的路径在本机不存在。
- **修复：** 用发行版自带的 curl 包，或者每次都用 `--cacert` 指定有效的证书包。

### 5. 证书包是空的或损坏了

更新中断、下载失败都可能留下一个空文件。

- **修复：** 重装软件包，或者执行 `update-ca-certificates`（Debian/Alpine）、`update-ca-trust`（RHEL 系）。

## 各环境修法

PHP、Windows、Docker 和 CI 的修法都是让证书包出现在 curl 实际查找的位置，并让运行 curl 的用户能读到。

**PHP / 宝塔：** php.ini 里的 `curl.cainfo` 或 `openssl.cafile` 指向不存在的 `cacert.pem` 时，PHP 的 cURL 扩展会报 77。在宝塔“PHP 管理 → 配置文件”里修正路径，或者删掉这两行改用系统证书包；见 [PHP cURL error 60](https://ssl.sh/zh/errors/php-curl-error-60/)。

**Windows：** Windows 自带的 curl.exe 使用系统证书库，不需要证书包文件。第三方 OpenSSL 版本的 curl 会在可执行文件旁边找 `curl-ca-bundle.crt`，或读 `CURL_CA_BUNDLE`，证书包从 curl.se 下载。

**Docker：** `ca-certificates` 要装在实际运行 curl 的那个阶段；多阶段构建常常只在构建阶段装了。

**CI（GitLab Runner、Jenkins、云效）：** 检查任务级变量，给某个任务设置的 `CURL_CA_BUNDLE` 可能被带到其他任务里。

## 不要这样做

这 3 种做法会关闭校验，或者让访问公网网站出新的错误。

- **加 `curl -k` 绕过去。** 那次请求就完全不校验了，应该修好证书包。
- **把证书包指向一张私有根证书。** `--cacert` 会替换默认列表，访问公网网站会变成 [报错 60](https://ssl.sh/zh/errors/curl-60-ssl-certificate-problem/)。私有根证书应该追加到 [系统信任库](https://ssl.sh/zh/glossary/trust-store/) 里。
- **从网上随便下载一个 `cacert.pem`。** 用系统包管理器，或者 curl.se 发布的证书包。
