# Windows Nginx 的 server block 与反向代理

> 用 server_name 托管多个域名，服务静态目录，反代 Node/Java 上游，并正确转发 Host/X-Forwarded 头。

**测试环境**

- 版本号: 26100.33650
- 版本: Standard / Datacenter
- 架构: x64
- 证据: E1
- 核验日期: 2026-10-29

## 一句话结论

一个 `server` 块 = 一个虚拟主机：

```nginx
server {
    listen 8082;
    server_name lab.local;

    root C:/nginx/html/lab;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
```

`server_name` 匹配 HTTP `Host`。没有匹配时，第一个/`default_server` 块应答。一个域名一个块，不是一个应用一个端口。

## 静态站

```nginx
server {
    listen 8082;
    server_name lab.local;
    root C:/sites/lab;
    index index.html;

    location /assets/ {
        expires 7d;
        add_header Cache-Control "public";
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}
```

Windows 路径用正斜杠。相对 `root` 相对 Nginx 工作目录，绝对路径更稳。

用 Host 头测试：

```powershell
curl.exe -H "Host: lab.local" http://127.0.0.1:8082/
```

## 反向代理

Node/Java/Python 上游在本机：

```nginx
upstream app_backend {
    server 127.0.0.1:3000;
    keepalive 16;
}

server {
    listen 8083;
    server_name app.local;

    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;
        proxy_read_timeout 60s;
    }
}
```

`proxy_pass` 后面加不加 URI 是两种行为：`http://app_backend` 保留请求 URI；`http://app_backend/` 会改路径。不要无意中加斜杠。

## WebSocket

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

location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 3600s;
}
```

`map` 必须在 `http` 块，不在 `server` 里。

## 验证

```powershell
cd C:\nginx
.\nginx.exe -t
.\nginx.exe -s reload
curl.exe -I -H "Host: lab.local" http://127.0.0.1:8082/
curl.exe -I -H "Host: app.local" http://127.0.0.1:8083/
Get-Content .\logs\error.log -Tail 50
```

所有域名都返回同一个站点：`server_name`/Host 没匹配，或另一个块是 `default_server`。反代 502：上游没监听或端口错。

> **警告: 不要在 location 里用 if 做路由**
>
> Nginx `location` 内的 `if` 行为反直觉。优先独立 `location`、`map`、`try_files`；用 `nginx -t` 和真实 Host 头验证。

## 实验室边界

E1。实验室只把 Nginx 1.28.0 跑在 8081，没有加第二个 server block 或上游。配置是 Server 2025 的验证路径。

## 来源

- [nginx — Server names](https://nginx.org/en/docs/http/server_names.html)
- [nginx — 反向代理](https://nginx.org/en/docs/http/ngx_http_proxy_module.html)
- [nginx — WebSocket 代理](https://nginx.org/en/docs/http/websocket.html)

---

来源页面: https://winbook.fyi/zh/server/web/nginx-sites/
