跳到主要内容

NextJS 使用 Nginx 反向代理并配置 HTTPS

· 阅读需 8 分钟

Next.js 是一个火热的 React 前端框架,由 Vercel 公司出品。说起 SSR 大家都会第一时间想到它,其内置的约定式路由,静态资源优化,各种 CSS 方案, turbopack 构建(rust 一统前端构建?)等功能也十分的出色。

因为是服务端渲染,所以肯定自带了后端服务,它默认使用 nodejsexpress 库一次部署就可以完成前端资源项目和后端 API 服务的部署。

Nginx 是一个高性能的负载均衡功能服务器,其强大的性能和稳定性深得人心,目前是大多数公司的 web 服务器首选。

Let’s Encrypt 是一种新的证书颁发机构 (CA),它提供了一种获取和安装免费 TLS/SSL 证书的简单方法,从而在 web 服务器上启用加密的 HTTPS。通过加密传输加持,使得我们的 Nginx 服务器更加的安全。

先决条件:

  1. 具有 sudo 权限用户的 CentOS 7 服务器。
  2. 拥有 nodenginx 初始环境。
  3. 拥有注册域名。
  4. DNS 记录(域名解析),将你的的域指向服务器的公共 IP 地址。 Let’s Encrypt 会验证你是否拥有它为其颁发证书的域

安装 Certbot 加密客户端

使用 Let’s Encrypt 获取 SSL 证书的第一步是在服务器上安装 certbot 软件。目前,最好的安装方式是通过 EPEL 存储库。

sudo yum install epel-release

启用存储库后, 安装 certbot-nginx 包:

sudo yum install certbot-nginx

启动 NextJS 项目

我们可以使用 pm2 让我们的 NextJS 服务在后台运行而不会一直占着终端的位置。

npm install -g pm2

# 进入到项目根目录下
pm2 start npm --name "next" -- start
pm2 stop next

设置 Nginx

如果还没有安装 Nginx

sudo yum install nginx

使用 systemctl 启动 Nginx

sudo systemctl start nginx

Certbot 可以为 Nginx 自动配置 SSL,但它需要能够在配置中找到正确的 server 块。它通过查找请求证书的域匹配的 server_name 参数来实现。

如果刚开始安装新的 Nginx,可以更新默认配置文件(已安装过忽略以下配置)

sudo vi /etc/nginx/nginx.conf

新增一个 server 块,配置 server_name 参数

server {
server_name www.example.com;

location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}

访问 www.example.com 这个域名的所有路径都会被反向代理到本机的 http://localhost:3000,(前提是该域名已经在域名服务商那里解析到了本机服务器的公网 ip 地址) 3000 是 NextJS 项目生产环境默认启动端口。

保存并退出,检查配置语法是否有误

sudo nginx -t

如果提示正确,则重启 Nginx 服务器

sudo systemctl reload nginx

更新防火墙

如果启用了防火墙,请确保端口 80 和 443 对传入流量开放。如果你没有运行防火墙,则忽略。

sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --runtime-to-permanent

准备就绪,现在可以运行 Certbot 并获取证书。

获取证书

sudo certbot --nginx

--nginx 代表使用 nginx 插件运行 certbot

如果是第一次运行 certbot,会提示输入电子邮件地址并同意服务条款。

紧接着会问你想要激活哪个域名的证书,输入数字选择固定的域名,多选以逗号隔开,输入空格则全选,最后回车确定

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: xx.com
2: www.xx.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

其他安装提示进行即可,最后成功会提示你证书的存放路径,并且 nginx 配置也会更新。

当然也可以加上 -d 参数运行 certbot,指定证书名称

sudo certbot --nginx -d www.xx.com

然后就可以重启 Nginx 服务器了(当然,你的 server 需要有个目标,是需要配置静态 html 路径或者 proxy_pass 反向代理地址的)

sudo systemctl reload nginx

设置自动续订

加密的证书只在 90 天内有效。这是为了鼓励用户自动化其证书续订过程。我们需要设置一个定期运行的命令来检查过期的证书并自动续订它们。

为了每天运行更新检查,我们将使用 cron,这是一种用于运行定期作业的标准系统服务。我们通过打开和编辑一个名为 crontab 的文件来告诉 cron 要做什么。

sudo crontab -e

文本编辑器将打开默认的 crontab,此时它是一个空文本文件。粘贴到以下行,然后保存并关闭:

crontab

15 3 * * * /usr/bin/certbot renew --quiet

15 3 * * * 部分表示 “每天上午 3:15 运行以下命令”。你也可以改成任何时间。

Certbotrenew 命令检查系统上安装的所有证书,并更新任何设置为在 30 天内过期的证书。--quiet 告诉 Certbot 不要输出信息或等待用户输入。

cron 现在会每天运行这个命令。所有已安装的证书会在到期前 30 天或更短时间内自动续订和重新加载。