FrankenPHP出站HTTPS请求SSL验证失败需配置PHP的cacert.pem证书包:下载CA证书、在php.ini中设置curl.cainfo和openssl.cafile为绝对路径、重启Caddy并验证。

FrankenPHP 本身不直接管理 CA 根证书,它复用底层 Caddy 的 TLS 栈和 PHP 的 OpenSSL/cURL 环境。当你用 FrankenPHP(通过 Caddy)访问外部 HTTPS 站点(比如 file_get_contents('https://api.example.com') 或 Symfony HttpClient 请求)时出现 “SSL certificate problem: unable to get local issuer certificate”,问题根源在 PHP 的证书验证环节——即 PHP 不知道该信任谁。
这不是 Caddy 的 HTTPS 服务配置问题,而是 FrankenPHP 运行的 PHP 进程发起出站请求时缺少可信根证书包。
✅ 正确配置根证书(让 FrankenPHP 发起的 HTTPS 请求能验证成功)
1. 下载权威 CA 证书包(cacert.pem)
从官方维护源获取最新版:
curl -o /etc/ssl/certs/cacert.pem https://curl.se/ca/cacert.pem
✅ 推荐路径:
/etc/ssl/certs/cacert.pem(Linux)或C:\php\extras\ssl\cacert.pem(Windows),确保路径稳定、可读。立即学习“PHP免费学习笔记(深入)”;
2. 配置 PHP 使用该证书包
FrankenPHP 使用系统级 PHP(如 /usr/bin/php 或 php.exe),需修改其 php.ini:
; 启用 OpenSSL 扩展(通常已启用,确认不被注释) extension=openssl ; 指定 cURL 和 OpenSSL 共用的根证书文件 curl.cainfo = "/etc/ssl/certs/cacert.pem" openssl.cafile = "/etc/ssl/certs/cacert.pem"
⚠️ 注意:
- 两个配置项都要设,作用不同:
curl.cainfo影响 cURL 请求,openssl.cafile影响file_get_contents()、stream_context_create()等原生 PHP 函数。 - 路径必须是绝对路径,且 PHP 进程有读取权限(
ls -l /etc/ssl/certs/cacert.pem检查)。
3. 重启 FrankenPHP(即重启 Caddy)
FrankenPHP 是 Caddy 的一个模块,重启 Caddy 即可加载新 PHP 配置:
sudo systemctl restart caddy # 或手动 reload sudo caddy reload
4. 验证是否生效
新建一个测试脚本 test-https.php:
<?php
var_dump(file_get_contents('https://httpbin.org/get'));
?>运行:
caddy run --config ./Caddyfile # 确保 FrankenPHP 正常启动后 # 然后用 curl 或浏览器访问该脚本,或 CLI 直接执行: php test-https.php
不报 SSL 错误即成功。
? 补充:如果目标是自签名/内部服务(如本地 Mercure Hub)
例如访问 https://localhost/.well-known/mercure 报错,说明 Caddy 自签的本地证书未被 PHP 信任:
- ✅ 最佳实践:用
mkcert生成 localhost 证书,并将 mkcert 的 rootCA.pem 加入系统信任库(mkcert -install已完成),再确保cacert.pem包含该 root(通常不需要额外操作,因 mkcert 的 root 已注入系统); - ❌ 不推荐:在代码中临时关闭验证(
CURLOPT_SSL_VERIFYPEER=false),这会带来安全风险,仅限调试; - ✅ 可选增强:把你的内部 CA 根证书追加进
cacert.pem:cat /path/to/internal-root-ca.crt >> /etc/ssl/certs/cacert.pem
? 常见误区提醒
- FrankenPHP 的
Caddyfile中配置的是它自己作为 HTTPS 服务器所用的证书(即别人访问你),不影响它作为客户端访问别人; - 不要改 Caddy 的
tls块去“解决 PHP 出站请求失败”,那是方向错误; - Alpine Linux 容器中默认无完整 CA 包,务必手动挂载
cacert.pem并配置php.ini; -
phpinfo()页面里搜索 “openssl” 和 “cURL”,确认Loaded CA file显示的是你设置的路径。
不复杂但容易忽略。



















