You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx同域名HTTPS首次请求失败求助(含证书验证问题)

解决Nginx HTTPS同域名部署下NextJS SSR的证书验证问题

兄弟,你遇到的unable to verify the first certificate问题,核心是SSL证书链不完整,或者NextJS在SSR场景下用isomorphic-unfetch发起请求时,服务器端的证书信任逻辑和浏览器不一样。结合你的配置和场景,我整理了几个靠谱的排查和解决步骤:

1. 先把Nginx的HTTPS证书配置补全

很多人部署HTTPS时只放了域名证书,漏掉了中间证书,导致客户端(包括服务器端的fetch请求)没法完成信任链验证。这是最常见的原因!

你的Nginx HTTPS server块得这么配才对:

server {
    listen 443 ssl;
    server_name my-domain.com www.my-domain.com;

    # 重点:要用包含中间证书的fullchain.pem,别只用单独的域名证书
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    # 可选但推荐的SSL安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # 前端NextJS SSR服务转发
    location / {
        proxy_pass http://customer-ssr;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 后端API转发,注意末尾的斜杠,避免路径重复
    location /api/ {
        proxy_pass http://your-backend-server:port/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# HTTP自动跳转到HTTPS
server {
    listen 80;
    server_name my-domain.com www.my-domain.com;
    return 301 https://$server_name$request_uri;
}

比如用Let's Encrypt的话,它会自动生成fullchain.pem和privkey.pem,直接用这两个就行,别用单独的cert.pem。

2. 搞定NextJS SSR里的fetch证书验证问题

在SSR场景下,isomorphic-unfetch在服务器端跑的时候,用的是Node.js的证书信任库,和浏览器的不是一套。如果你的证书是自签名的,或者CA不被Node默认信任,就会报错。

方案A:让Node信任你的证书(正规CA证书优先用这个)

  • 如果你用的是正规CA颁发的证书,先升级Node.js到14+版本,新版的根证书库更全,大概率能解决问题。
  • 如果是自签名证书,测试环境可以临时禁用验证(生产环境绝对不能这么干!):
import fetch from 'isomorphic-unfetch';
import https from 'https';

// 仅测试环境使用,生产环境禁止!
const agent = new https.Agent({ rejectUnauthorized: false });
const res = await fetch('https://my-domain.com/api/your-endpoint', { agent });

方案B:SSR直接请求后端内网地址(最推荐)

既然前后端都在同一服务器或者内网里,SSR时完全没必要绕公网HTTPS请求my-domain.com/api/,直接请求后端的内网地址就行,既避免了证书问题,还更快。

你可以在NextJS里通过环境变量区分客户端和服务器端的API地址:

// 根据运行环境切换API地址
const API_BASE = typeof window !== 'undefined' 
  ? '/api' // 客户端走Nginx转发
  : 'http://127.0.0.1:你的后端端口'; // SSR时直接打内网地址

const res = await fetch(`${API_BASE}/your-endpoint`);

3. 验证证书链是否正常

用openssl命令检查下你的证书链有没有问题:

openssl s_client -connect my-domain.com:443 -servername my-domain.com

看输出里的Verify return code,如果是0 (ok)就没问题;如果是20 (unable to get local issuer certificate),那就是缺中间证书,赶紧把中间证书加到fullchain.pem里。


内容的提问来源于stack exchange,提问作者Vo Manh Kien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:00:31