个人项目常见的部署方式是:应用只监听本机端口,Nginx 负责接收公网请求、终止 HTTPS,并把流量转发给应用。这样既能隐藏应用端口,也能统一管理证书、压缩、访问日志和安全响应头。

下面用 example.com 和本机 3000 端口演示一套可维护的最小配置。

1. 部署前检查

先确认三个条件:

  1. 域名 A/AAAA 记录已经指向服务器;
  2. 安全组和防火墙允许 TCP 80、443;
  3. 应用在服务器本机可以访问。
curl -I http://127.0.0.1:3000
dig +short example.com

如果本机应用都无法访问,Nginx 配置得再正确也只会得到 502 Bad Gateway。

2. 安装 Nginx

sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
nginx -v

3. 编写反向代理配置

创建 /etc/nginx/sites-available/example.com:

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

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log warn;

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

        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}

启用站点并检查语法:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginx

每次修改都先执行 nginx -t。语法失败时不要 reload,更不要急着 restart。

4. 申请 Let's Encrypt 证书

Ubuntu 上可以使用 Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Certbot 会验证域名,并帮助写入 HTTPS 配置。申请前要保证 80 端口能从公网访问,否则 HTTP-01 验证会失败。

5. 检查 HTTPS 和自动续期

curl -I https://example.com
sudo systemctl status certbot.timer
sudo certbot renew --dry-run

renew --dry-run 成功比“定时器显示正在运行”更有说服力,因为它验证了完整的续期流程。

6. 加入基础安全响应头

确认站点完全支持 HTTPS 后,可以在 HTTPS 的 server 块中增加:

add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Strict-Transport-Security "max-age=31536000" always;

HSTS 会让浏览器在有效期内强制使用 HTTPS。只有在证书续期可靠、所有子域策略明确后再考虑加入 includeSubDomains。

7. 常见故障定位

502 Bad Gateway

curl -v http://127.0.0.1:3000
sudo ss -lntp | grep 3000
sudo tail -n 100 /var/log/nginx/example.com.error.log

重点检查应用是否运行、监听地址是否正确,以及 Nginx 是否有访问该端口的权限。

证书申请失败

dig +short example.com
curl -I http://example.com/.well-known/acme-challenge/test
sudo ufw status

同时检查 CDN 代理、AAAA 记录和云安全组。错误的 IPv6 解析也是常见原因。

修改配置后没有生效

sudo nginx -T | less
sudo nginx -t
sudo systemctl reload nginx

nginx -T 可以看到最终合并后的全部配置,适合定位重复的 server_name 或加载了错误文件的问题。

8. 回滚思路

修改前保留一份已验证配置:

sudo cp /etc/nginx/sites-available/example.com \
  /etc/nginx/sites-available/example.com.bak

如果新配置有问题,恢复备份、执行 nginx -t,再 reload。一个可靠的部署流程,应该让错误配置无法进入运行状态。

Nginx 的价值不只是“把端口转发出去”,而是为应用建立一层稳定、可观察、可回滚的公网入口。