多站点、静态文件与 TLS 接入
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read332 words

多站点、静态文件与 TLS 接入

当一台机器要承载多个站点时,Nginx 的价值会变得非常明显。

多站点结构

graph TD A["80 / 443 入口"] --> B{server_name 匹配} B -->|app.example.com| C[应用 A :3000] B -->|admin.example.com| D[应用 B :3001] B -->|static.example.com| E[静态文件目录] C --> F[HTTPS 自动跳转] D --> F E --> F

多站点 Nginx 配置文件结构

每个站点一个配置文件,放在 /etc/nginx/sites-available/,再软链接到 sites-enabled/

# 目录结构
/etc/nginx/
├── nginx.conf                    # 主配置(不改动)
├── sites-available/
│   ├── app.example.com.conf      # 应用 A
│   └── admin.example.com.conf    # 应用 B
└── sites-enabled/
├── app.example.com.conf -> ../sites-available/app.example.com.conf
└── admin.example.com.conf -> ../sites-available/admin.example.com.conf
# 启用站点(创建软链接)
sudo ln -s /etc/nginx/sites-available/app.example.com.conf /etc/nginx/sites-enabled/
# 禁用站点(删除软链接,不删原文件)
sudo rm /etc/nginx/sites-enabled/app.example.com.conf

完整多站点配置示例

# /etc/nginx/sites-available/app.example.com.conf
# HTTP → HTTPS 自动跳转
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主配置
server {
listen 443 ssl;
server_name app.example.com;
# SSL 证书(由 certbot 自动填充,见下方)
ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# 安全头部
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options SAMEORIGIN;
# 反向代理到应用
location / {
proxy_pass http://127.0.0.1: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;
}
}
# /etc/nginx/sites-available/admin.example.com.conf(第二个站点)
server {
listen 80;
server_name admin.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name admin.example.com;
ssl_certificate     /etc/letsencrypt/live/admin.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/admin.example.com/privkey.pem;
# 静态文件服务(单独站点或前端构建产物)
root /var/www/admin;
index index.html;
location / {
try_files $uri $uri/ /index.html;  # SPA 路由支持
}
}

Certbot 自动申请 TLS 证书

# 安装 Certbot
sudo apt install certbot python3-certbot-nginx
# 申请证书(Certbot 自动修改 Nginx 配置)
sudo certbot --nginx -d app.example.com
# 多域名一起申请
sudo certbot --nginx -d app.example.com -d www.app.example.com
# 测试续期(不实际续期,验证流程是否正常)
sudo certbot renew --dry-run
# 查看证书到期时间
sudo certbot certificates

Certbot 会自动配置 systemd.timer 定期续期,验证:

systemctl list-timers certbot*
# → certbot.timer  每日运行,证书到期前 30 天续期

验证配置和重载

# 语法检查(修改配置后必须执行)
sudo nginx -t
# → nginx: configuration file /etc/nginx/nginx.conf test is successful
# 重载配置(不中断现有连接)
sudo systemctl reload nginx
# 查看 Nginx 错误日志
sudo tail -f /var/log/nginx/error.log
# 验证 HTTPS
curl -I https://app.example.com
# → HTTP/2 200
# 验证跳转
curl -I http://app.example.com
# → HTTP/1.1 301 Moved Permanently
# → Location: https://app.example.com/

常见误区

误区 正确做法
所有站点配置写在一个文件里 每站点一个文件,放 sites-available/,软链到 sites-enabled/
先配 HTTPS 再测 HTTP 是否通 先在 HTTP 验证站点可达,再申请证书接 HTTPS
忘记续期证书 Certbot 自动续期,但要验证 certbot renew --dry-run 通过
修改 Nginx 配置后直接 restart nginx -t 验证语法,再 systemctl reload(reload 不中断连接)
proxy_pass 后忘记传 X-Real-IP 不传则应用看到的 IP 始终是 127.0.0.1

本节执行清单

下一节应用进程与 Nginx 协同——把入口和应用生命周期真正串起来。