Nginx 反向代理+SSL证书一键配置指南

概述

做个人项目或者小团队开发,最头疼的往往不是写代码,而是把服务部署上线。域名买了,服务跑起来了,但浏览器里全是"不安全"的红色警告,用户看了直摇头。

今天教你用 Nginx 做反向代理,加上 Certbot 自动申请 Let’s Encrypt 免费 SSL 证书。整个过程大约 15 分钟,证书自动续期,再也不用管了。

反向代理是什么?简单说就是它站在你的服务前面,替用户处理请求。用户访问 443 端口(HTTPS),它解密后把请求转发给你的后端服务。这样你的服务不用操心加密和域名绑定,专注写代码就好。

准备工作

你需要以下条件和环境:

  • 一台公网 VPS:CentOS 7+、Ubuntu 20.04+ 或 Debian 11+ 都可以
  • 一个已解析到服务器 IP 的域名:比如 api.example.com,在 DNS 里加一条 A 记录
  • 服务器已开放 80 和 443 端口:防火墙和安全组都要放行
  • root 或 sudo 权限

以下示例以 Ubuntu 22.04 为例,CentOS 用户把 apt 换成 yum 即可。

安装 Nginx

先装 Nginx,这是反向代理的核心。

sudo apt update
sudo apt install nginx -y

安装完成后,确认 Nginx 在运行:

sudo systemctl status nginx

看到 active (running) 就说明没问题。如果没启动,执行:

sudo systemctl enable nginx
sudo systemctl start nginx

安装 Certbot

Certbot 是 Let’s Encrypt 的官方客户端,能自动申请和配置证书。

sudo apt install certbot python3-certbot-nginx -y

配置 Nginx 反向代理

假设你有一个后端服务跑在 localhost:3000,你想让 api.example.com 代理到这个服务。

编辑 Nginx 配置文件:

sudo nano /etc/nginx/sites-available/api.example.com

写入以下内容:

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://localhost:3000;
        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;
    }
}

保存后,创建软链接启用配置:

sudo ln -s /etc/nginx/sites-available/api.example.com /etc/nginx/sites-enabled/

测一下配置有没有语法错误:

sudo nginx -t

看到 syntax is oktest is successful 就对了。然后重载 Nginx:

sudo systemctl reload nginx

申请 SSL 证书

现在配置好了 HTTP 的反向代理,接下来让 Certbot 帮你申请 HTTPS 证书并自动修改 Nginx 配置。

sudo certbot --nginx -d api.example.com

第一次运行会让你填邮箱(用于证书过期提醒)和同意协议。然后 Certbot 会自动:

  1. 验证你对域名的控制权
  2. 向 Let’s Encrypt 申请证书
  3. 自动修改 Nginx 配置,启用 HTTPS
  4. 设置 HTTP 自动跳转到 HTTPS

完成后你会看到类似这样的提示:

Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/api.example.com/fullchain.pem

验证搭建是否成功

打开浏览器,访问 https://api.example.com。如果看到你的后端服务页面,且地址栏有绿色小锁,说明一切正常。

也可以用命令行验证:

curl -I https://api.example.com

返回的状态码应该是 200,并且响应头里会包含 strict-transport-security,说明 HSTS 已经启用。

证书信息也可以用这个命令查看:

echo | openssl s_client -servername api.example.com -connect api.example.com:443 2>/dev/null | openssl x509 -noout -dates

输出会显示证书的生效日期和过期日期,Let’s Encrypt 的证书有效期为 90 天。

配置自动续期

Let’s Encrypt 的证书只有 90 天有效期,但 Certbot 自带自动续期机制。检查续期定时器:

sudo systemctl list-timers | grep certbot

应该能看到每天会自动运行续期检查。如果想手动测试续期流程(不会真的续期,只是测试):

sudo certbot renew --dry-run

看到 Congratulations, all renewals succeeded 就说明自动续期配置正确。

常见问题

问题一:申请证书时报 DNS validation failed

原因通常是 DNS 没生效,或者域名解析指向了错误的 IP。用这个命令检查:

dig api.example.com

确保返回的 IP 和你服务器公网 IP 一致。如果不一致,等 DNS 传播(通常几分钟到几小时)。

问题二:Nginx 启动报错 port 80 already in use

可能是 Apache 或其他服务占用了 80 端口。用这个命令查看:

sudo lsof -i :80

关掉占用端口的服务,或者修改 Nginx 监听端口。

问题三:后端服务返回的是原始 IP 而不是用户真实 IP

在 Nginx 配置里加上这几行就行:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

后端代码里读取 X-Real-IPX-Forwarded-For 头部即可。

问题四:证书申请成功但浏览器还是显示不安全

清除浏览器缓存,或者用无痕模式重新打开。有时候浏览器会缓存之前的 HSTS 策略。也可以在地址栏手动忽略警告继续访问。


反向代理+SSL证书是部署Web服务的标配,学会这套流程,后续加服务直接复用 Nginx 配置就行。

你的服务上线了吗?有没有遇到过证书或者 Nginx 配置的问题?