
👋 先说两句废话:搭过生产环境的老铁都知道,反向代理这东西属于"不装不知道,一装真香"的类型。你要是只跑一个服务还好说,一旦需要同时跑 API、Web、自动化工具……还暴露着端口裸奔,那酸爽谁用谁知道。
今天来讲讲怎么在 Ubuntu 服务器上用 Nginx 配反向代理 + 免费 SSL(Let's Encrypt),全程中文,步骤清晰,代码直接复制能用。
先科普一下概念。Nginx 反向代理简单说就是:客户端请求先打到 Nginx,Nginx 再帮你把请求转发到后端真实服务(比如你跑在 3000 端口的 Node.js API)。
为什么要这么搞?好处多了去了:
举个例子:你在服务器上跑了个 Node.js API(端口 3000)和 Python Flask 应用(端口 5000),有了反向代理,外部只要访问 api.example.com 和 app.example.com 就够了,端口?不存在的。
先 SSH 登录服务器,更新一下包管理器,然后安装 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;
}
}
解释一下关键配置:
upstream backend_service:定义后端服务地址,改成你自己的端口server_name api.example.com:换成你的真实域名proxy_set_header 系列:这些 header 很关键,保证后端服务能拿到真实客户端信息(IP、协议等)测一下配置语法:
sudo nginx -t
看到 syntax is ok 就可以 reload 了:
sudo systemctl reload nginx
现在访问 http://api.example.com 应该就能代理到你后端了。不过还是明文传输,HTTPS 走起。
这步是精髓,一条命令搞定一切,包括自动续期:
sudo certbot --nginx -d api.example.com
Certbot 会问几个问题:
Certbot 会自动修改 Nginx 配置,启用 HTTPS。配置大概长这样:
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;
}
}
测一下语法并 reload:
sudo nginx -t
sudo systemctl reload nginx
搞定!现在访问 https://api.example.com 就是加密连接了。证书有效期 90 天,Certbot 会通过 systemd timer 自动续期,完全不用你管。
验证一下自动续期定时器是否在跑:
sudo systemctl status certbot.timer
看到 active 就放心了。
光有 HTTPS 还不够,来点安全响应头,让配置更健壮。
在 HTTPS server 块里(ssl_dhparam 之后)添加:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
这些响应头分别防止:点击劫持、MIME 类型嗅探、XSS 攻击、referrer 信息泄露,并且强制 HTTPS。
怕被 DDoS 或暴力破解?加个限速。在 server 块外面(文件顶部)添加:
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
然后在 HTTPS server 块里应用:
limit_req zone=general burst=20 nodelay;
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ ~$ {
deny all;
access_log off;
log_not_found off;
}
省流量加快速,在 server 块外面加:
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
gzip_disable "MSIE [1-6]\.";
测一下 reload:
sudo nginx -t
sudo systemctl reload nginx
如果你要跑多个服务,配置起来也很简单,多加几个 upstream 就好:
upstream api_backend {
server localhost:3000;
keepalive 32;
}
upstream app_backend {
server localhost:5000;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name api.example.com app.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://api_backend;
proxy_http_version 1.1;
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;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
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;
}
}
每个域名分开配置,独立证书,独立后端,清晰明了。
配置 Nginx 反向代理 + Let's Encrypt SSL 这套组合拳,成本为零(证书免费),效果拉满。你得到了:
原文链接:How to Set Up Nginx Reverse Proxy with SSL (Let's Encrypt)