# Nginx 配置教程 — 多子域名反向代理实战

> 基于 wanyue.online 服务器实际配置编写，2026-05-30

---

## 一、架构概览

本教程展示如何用 Nginx 将 7 个独立项目部署在 7 个子域名下，共享一个 SSL 证书。

```
互联网 → Nginx (80/443) → 各后端服务
                ├── wanyue.online       → Halo 博客      (:8090)
                ├── api.wanyue.online    → One API        (:3000)
                ├── gist.wanyue.online   → Opengist       (:6157)
                ├── files.wanyue.online  → File Hub       (:8091)
                ├── pdf.wanyue.online    → PDFCraft       (静态文件)
                ├── ui.wanyue.online     → 湾悦 UI        (静态文件)
                └── love.wanyue.online   → Love           (静态文件)
```

### 为什么用子域名而不是路径？

| 方式 | 示例 | 问题 |
|------|------|------|
| 路径 | `wanyue.online/login` | 不同项目路径可能冲突；SPA 路由需逐个匹配 |
| 子域名 | `api.wanyue.online` | 完全隔离；`location /` 即可，零冲突 |

---

## 二、前置准备

### 1. DNS 解析

在 DNS 管理后台添加 A 记录，所有子域名指向同一台服务器：

```
wanyue.online  A  47.98.55.249
api            A  47.98.55.249
gist           A  47.98.55.249
files          A  47.98.55.249
pdf            A  47.98.55.249
ui             A  47.98.55.249
love           A  47.98.55.249
```

验证：
```bash
dig +short api.wanyue.online A
# 输出: 47.98.55.249
```

### 2. 安装 Nginx

```bash
apt update && apt install nginx certbot python3-certbot-nginx -y
```

---

## 三、配置文件结构

Nginx 配置采用 Debian/Ubuntu 风格的两目录结构：

```
/etc/nginx/
├── nginx.conf              # 主配置（一般不改）
├── sites-available/        # 所有站点定义放这里
│   └── wanyue              # 我们的多域名配置
└── sites-enabled/          # 启用的站点（软链接）
    └── wanyue -> ../sites-available/wanyue
```

操作命令：
```bash
# 创建配置
vim /etc/nginx/sites-available/wanyue
# 启用
ln -s /etc/nginx/sites-available/wanyue /etc/nginx/sites-enabled/
# 禁用旧配置
rm /etc/nginx/sites-enabled/old-config
# 检查语法
nginx -t
# 重载
nginx -s reload
```

---

## 四、Server Block 详解

每个服务由两个 server block 组成：HTTP 重定向 + HTTPS 服务。

### 模式一：反向代理（Halo / One API / Opengist / File Hub）

```
server {
    listen 80;
    listen [::]:80;
    server_name api.wanyue.online;
    return 301 https://$host$request_uri;    # HTTP → HTTPS
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name api.wanyue.online;

    ssl_certificate     /etc/letsencrypt/live/wanyue.online/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wanyue.online/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    client_max_body_size 50m;               # 上传限制（可选）

    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;
    }
}
```

关键参数说明：

- `listen 443 ssl` — 启用 HTTPS
- `proxy_pass http://127.0.0.1:3000` — 转发到本地服务
- `proxy_set_header Host $host` — 保持原始域名，后端才能识别子域名
- `proxy_set_header X-Forwarded-Proto $scheme` — 告诉后端用户用的是 https
- `return 301 https://$host$request_uri` — 永久重定向到 HTTPS

### Halo 特殊处理：WebSocket

Halo 博客需要 WebSocket 支持（实时通知），额外加两行：

```
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
```

其中 `$connection_upgrade` 变量在 `/etc/nginx/nginx.conf` 的 http 块中定义：

```
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
```

### 模式二：静态文件（PDFCraft / 湾悦 UI / Love）

```
server {
    listen 80;
    listen [::]:80;
    server_name ui.wanyue.online;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name ui.wanyue.online;
    # ... SSL 配置同上 ...

    root /local/usr/wanyue-ui/current/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;   # SPA 回退
    }
}
```

关键参数：

- `root /path/to/files` — 文件根目录
- `index index.html` — 默认首页
- `try_files $uri $uri/ /index.html` — 先尝试精确匹配文件，再尝试目录，最后回退到 index.html（SPA 前端路由必需）

---

## 五、SSL 证书

### 申请多域名证书

certbot 的 `--nginx` 插件会自动读取 Nginx 配置中的 server_name 并处理验证：

```bash
certbot --nginx \
  -d wanyue.online \
  -d api.wanyue.online \
  -d gist.wanyue.online \
  -d files.wanyue.online \
  -d pdf.wanyue.online \
  -d ui.wanyue.online \
  -d love.wanyue.online \
  --non-interactive --agree-tos --email admin@wanyue.online
```

7 个域名共享同一个证书（SAN 证书），有效期 90 天。

### 自动续期

certbot 安装后自动注册 systemd timer：

```bash
systemctl status certbot.timer
# 每天检查两次，到期前自动续期
```

手动测试续期：
```bash
certbot renew --dry-run
```

---

## 六、常用运维命令

```bash
# 检查配置语法
nginx -t

# 重载配置（不中断服务）
nginx -s reload

# 完全重启
systemctl restart nginx

# 查看监听端口
ss -tlnp | grep nginx

# 查看日志
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

# 测试单个域名
curl -sI https://api.wanyue.online/

# 测试 HTTP→HTTPS 跳转
curl -sI http://api.wanyue.online/ | grep Location
```

---

## 七、安全建议

### 已在用的

- 全站 HTTPS，HTTP 自动 301 跳转
- Let's Encrypt 免费证书，自动续期

### 可选加强

```nginx
# 在每个 HTTPS server block 中添加：

# HSTS（仅 HTTPS，浏览器强制记忆）
add_header Strict-Transport-Security "max-age=63072000" always;

# 隐藏 Nginx 版本号（nginx.conf http 块）
server_tokens off;
```

---

## 八、故障排查

| 症状 | 可能原因 | 检查命令 |
|------|----------|----------|
| 502 Bad Gateway | 后端服务未启动 | `ss -tlnp \| grep <port>` |
| 404 Not Found | 路径/root 配置错误 | 检查 `root` 和 `try_files` |
| SSL 证书错误 | 证书过期或域名不匹配 | `certbot certificates` |
| 重定向死循环 | HTTP/HTTPS block 混合 | 检查是否拆成了两个 server |
| 静态资源不加载 | SPA 路由未配置 fallback | 确认有 `try_files ... /index.html` |

---

## 九、与旧配置对比

| | 旧方式（路径） | 新方式（子域名） |
|---|---|---|
| 配置复杂度 | 高（大量 location 正则） | 低（每个项目一个 server） |
| 路径冲突风险 | 有（`/login` vs 博客路由） | 无 |
| 新增项目 | 需要找空路径 | 加一条 DNS + 一个 server block |
| 独立限流/缓存 | 困难 | 简单 |
| 配置文件行数 | 130 行（7 个项目挤一起） | 189 行（结构清晰） |

---

## 十、完整配置文件

配置文件的副本可从以下地址获取：
https://files.wanyue.online/2026/05-30/nginx-wanyue.conf
