site logo

Marico's space

Nginx 反向代理 + SSL 实战:免费的 Let's Encrypt 证书用起来

服务器技术 2026-04-25 23:05:13 7

【译者前言】说实话,之前我自己配 Nginx 反向代理的时候踩了不少坑,尤其是 SSL 这块,光是理解 Let's Encrypt 的工作方式就花了不少时间。这篇文章的好处在于,它把整个流程梳理得很清晰,从安装到配置再到自动续期,一步一步都有覆盖,读完就能上手实践。不需要你有多少运维经验,跟着走就行。

cover

你需要准备以下内容:

  • SSH 访问 Linux 服务器(推荐 Ubuntu 20.04 或更高版本)
  • 指向服务器 IP 地址的域名
  • 基本的命令行知识

理解 Nginx 反向代理架构

我管理生产服务器多年,很早就明白了一个道理:反向代理是基础设施的最佳拍档。与保护客户端的正向代理不同,反向代理位于面向互联网的流量和内部应用程序之间。这种架构为你提供负载均衡、SSL 终止、安全加固,以及在单个域名下运行多个服务的能力。

这为什么重要:如果你运行多个后端服务——比如 Node.js API 运行在端口 3000,Python Flask 应用运行在端口 5000——反向代理让客户端可以通过 api.example.comapp.example.com 访问这两个服务,而无需暴露内部端口。配合 Let's Encrypt SSL,你就拥有了企业级的免费加密。

说实话,以前没有 Let's Encrypt 的时候,配 SSL 还得花钱买证书,流程麻烦得很。现在有免费的了,没理由不用。

安装 Nginx 和 Certbot

首先,SSH 登录到你的服务器。你的域名应该已经指向服务器的 IP 地址(如果没有,请在域名注册商那里更新 DNS 记录,这通常需要几分钟到几小时生效)。

更新包管理器并安装 Nginx:

sudo apt update
sudo apt upgrade -y
sudo apt install -y nginx

启动 Nginx 并设置开机自启:

sudo systemctl start nginx
sudo systemctl enable nginx

检查 Nginx 是否正在运行:

sudo systemctl status nginx

你应该看到输出中显示 active (running)。现在安装 Certbot(Let's Encrypt 客户端)和 Nginx 插件:

sudo apt install -y certbot python3-certbot-nginx

验证安装:

certbot --version

很好。现在我们准备开始配置。

配置第一个反向代理

假设你有一个后端服务运行在 localhost:3000(可能是 Node.js 应用、Python 服务或任何 HTTP 服务)。你想通过 api.example.com 安全地暴露它。

打开 Nginx 配置目录:

sudo nano /etc/nginx/sites-available/default

用以下配置替换整个文件:

upstream backend_service {
    server localhost:3000;
    keepalive 32;
}

server {
    listen 80;
    listen [::]:80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend_service;
        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_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
}

让我详细解释一下这些配置(说实话这里的 header 设置确实容易漏掉,导致后端拿不到真实客户端信息):

  • upstream backend_service:定义流量去向。指向你实际的后端端口。
  • listen 80:监听 HTTP(Certbot 会将其升级为 HTTPS)。
  • server_name api.example.com:你的域名。将其改为你实际的域名。
  • proxy_pass:将请求路由到后端服务。
  • proxy_set_header 指令:保留客户端信息(IP、协议、域名),让你的后端应用看到真实的客户端。

测试配置语法:

sudo nginx -t

如果看到 syntax is ok,重新加载 Nginx:

sudo systemctl reload nginx

如果你现在在浏览器中访问 http://api.example.com,它应该会代理到端口 3000 上的后端服务。不过连接是未加密的——下一步就来解决这个问题。

配置 SSL(Let's Encrypt)

这就是见证奇迹的时刻。Certbot 自动化了整个 SSL 设置过程,包括续订。运行 Certbot 并使用 Nginx 插件:

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

Certbot 会问几个问题:

  1. 输入你的电子邮件地址(用于续订提醒)。
  2. 接受 Let's Encrypt 服务条款。
  3. 可选:与 EFF 分享你的电子邮件(他们的选择)。

当被问到将 HTTP 流量重定向到 HTTPS 时,选择 "2"

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.

1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, unless you have a specific reason otherwise.

说实话,如果你不知道选什么,选 2 就对了,自动跳转 HTTPS 省心省力。

Certbot 自动修改你的 Nginx 配置以启用 HTTPS 并重定向 HTTP 流量。你的配置现在应该是这样的:

sudo cat /etc/nginx/sites-available/default

你会看到类似这样的内容(Certbot 添加了 HTTPS server 块并修改了 HTTP 块):

upstream backend_service {
    server localhost:3000;
    keepalive 32;
}

server {
    listen 80;
    listen [::]:80;
    server_name api.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://backend_service;
        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_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
}

测试你的配置

验证 HTTPS 是否正常工作:

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

你应该看到:

HTTP/2 200

如果看到 Connection refused,检查以下几点(这里确实很容易出问题,尤其是防火墙):

  1. Nginx 是否正在运行:sudo systemctl status nginx
  2. 防火墙是否允许 443 端口:sudo ufw allow 443
  3. 后端服务是否在端口 3000 上运行

自动续期

Let's Encrypt 证书有效期为 90 天。Certbot 安装时自动配置了续订 cron 任务。

验证续订定时器是否激活:

sudo systemctl status certbot.timer

测试自动续订(dry run):

sudo certbot renew --dry-run

如果看到 Congratulations, all renewals succeeded,表示一切正常。

说实话,这里我建议大家定期手动跑一下 renew dry run,确保定时器没问题。之前遇到过定时器没激活的情况,证书过期了才发现,那就麻烦了。

总结

通过本指南,你已学会了:

  • ✅ Nginx 反向代理配置
  • ✅ 使用 Let's Encrypt 申请免费 SSL 证书
  • ✅ 自动 HTTPS 重定向
  • ✅ 证书自动续订

你现在拥有了一个生产级别的反向代理设置,完全免费,且自动化维护。

记住定期检查证书到期时间,并确保你的 DNS 配置始终指向正确的服务器 IP。