> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Nginx 完全指南
- URL: https://blog.vercanti.com/nginx-wan-quan-zhi-nan/
- Published: 2026-08-28T14:34:26.000Z
- Updated: 2026-08-28T14:56:30.000Z
- Description: 相关文档：Docker Compose完全指南(/docker-compose-wan-quan-zhi-nan/) Docker初级指南(/docker-chu-ji-zhi-nan/) FastAPI完全指南(/fastapi-wan-quan-zhi-nan/) Nginx 是高性能的 HTTP 服务器和反向代理服务器，常见用途： 子 location 块使用 add_header 后，父块的 add_header 会失效。需在每个 location 都添加，或使用 headers-more-nginx-module 模块。 每次修改配置前先 ng
- Author: yellowdog
- Tags: DevOps

> 官方文档：<https://nginx.org/en/docs/>  
> 适用版本：Nginx 1.26（2026-05-07 核实）

相关文档：[Docker Compose完全指南](https://blog.vercanti.com/docker-compose-wan-quan-zhi-nan/) [Docker初级指南](https://blog.vercanti.com/docker-chu-ji-zhi-nan/) [FastAPI完全指南](https://blog.vercanti.com/fastapi-wan-quan-zhi-nan/)

---

## 1\. 基础概念

### Nginx 是什么

Nginx 是高性能的 HTTP 服务器和反向代理服务器，常见用途：

| 用途     | 说明                              |
| ------ | ------------------------------- |
| 静态文件服务 | 直接托管 HTML/CSS/JS/图片，性能极高        |
| 反向代理   | 将请求转发给后端服务（FastAPI/Node/Django） |
| 负载均衡   | 将流量分发到多个后端实例                    |
| SSL 终止 | 在 Nginx 层处理 HTTPS，后端用 HTTP      |
| 缓存     | 缓存后端响应，减少后端压力                   |
| 限流     | 防止请求过多压垮后端                      |

### 配置文件结构

```
/etc/nginx/
  nginx.conf           主配置文件
  conf.d/              额外配置目录（nginx.conf 会 include 这里）
    default.conf
    myapp.conf
  sites-available/     站点配置（Ubuntu/Debian）
  sites-enabled/       已启用站点的软链接

```

---

## 2\. 配置文件语法

```nginx
# nginx.conf 总体结构
user nginx;
worker_processes auto;          # 工作进程数（auto = CPU 核数）
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;    # 每个 worker 最大连接数
    use epoll;                  # Linux 使用 epoll（高性能）
    multi_accept on;            # 一次接受多个连接
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;
    gzip on;

    # 包含所有站点配置
    include /etc/nginx/conf.d/*.conf;
}

```

---

## 3\. server 块 — 虚拟主机

```nginx
server {
    listen 80;                      # 监听端口
    listen [::]:80;                 # IPv6
    server_name example.com www.example.com;  # 匹配的域名

    root /var/www/html;             # 根目录
    index index.html index.htm;

    # 访问日志
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location / {
        try_files $uri $uri/ /index.html;  # SPA 路由
    }
}

```

---

## 4\. location 块

### 匹配规则（优先级从高到低）

| 修饰符  | 说明            | 示例                           |
| ---- | ------------- | ---------------------------- |
| \=   | 精确匹配          | location = /favicon.ico      |
| ^\~  | 前缀匹配（优先，不走正则） | location ^\~ /static/        |
| \~   | 正则匹配（区分大小写）   | location \~ \\.php$          |
| \~\* | 正则匹配（不区分大小写）  | location \~\* \\.(jpg\|png)$ |
| 无修饰符 | 普通前缀匹配        | location /api/               |

```nginx
# 精确匹配根路径
location = / {
    return 301 /index.html;
}

# 静态文件（前缀优先，不走正则）
location ^~ /static/ {
    alias /var/www/static/;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# API 反向代理
location /api/ {
    proxy_pass http://backend:8000/;
    include /etc/nginx/proxy_params;
}

# 正则匹配图片
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
    expires 7d;
    add_header Cache-Control "public";
}

```

---

## 5\. 反向代理

### 基础反向代理

```nginx
# /etc/nginx/conf.d/myapp.conf
upstream backend {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend;

        # 必须设置的代理头
        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 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;

        # 缓冲区
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
}

```

### 创建 proxy\_params 文件（复用）

```nginx
# /etc/nginx/proxy_params
proxy_set_header Host $http_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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;  # WebSocket

```

---

## 6\. HTTPS 配置

### 手动证书

```nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # SSL 优化
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    # 现代 TLS 配置（来自 Mozilla SSL Config Generator）
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    location / {
        proxy_pass http://backend;
        include /etc/nginx/proxy_params;
    }
}

# HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

```

### Let's Encrypt（Certbot）

```bash
# 安装 certbot
apt install certbot python3-certbot-nginx

# 自动申请证书并配置 Nginx
certbot --nginx -d example.com -d www.example.com

# 自动续期测试
certbot renew --dry-run

# 自动续期（通常 certbot 安装时会自动创建 cron 任务）
# 0 12 * * * /usr/bin/certbot renew --quiet

```

---

## 7\. 负载均衡

```nginx
upstream backend {
    # 轮询（默认）
    server 10.0.0.1:8000;
    server 10.0.0.2:8000;
    server 10.0.0.3:8000;

    # 权重
    server 10.0.0.1:8000 weight=3;
    server 10.0.0.2:8000 weight=1;

    # IP Hash（同一 IP 总路由到同一服务器，保持会话）
    ip_hash;

    # 最少连接数
    least_conn;

    # 健康检查（商业版 Nginx Plus 支持主动检查，开源版用 max_fails）
    server 10.0.0.1:8000 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8000 backup;  # 备用服务器
}

```

---

## 8\. 常用功能

### Gzip 压缩

```nginx
http {
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;       # 小于 1KB 不压缩
    gzip_comp_level 6;          # 压缩级别 1-9（6 是性价比最高）
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml;
}

```

### 限流

```nginx
http {
    # 定义限流区域（$binary_remote_addr 按 IP 限流）
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/m;

    server {
        # API 接口：每秒 10 个请求，允许突发 20 个
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            limit_req_status 429;
            proxy_pass http://backend;
        }

        # 登录接口：每分钟 1 次（防止暴力破解）
        location /api/login {
            limit_req zone=login;
            proxy_pass http://backend;
        }
    }
}

```

### 跨域（CORS）

```nginx
location /api/ {
    add_header Access-Control-Allow-Origin "https://frontend.example.com" always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
    add_header Access-Control-Allow-Credentials "true" always;

    if ($request_method = OPTIONS) {
        add_header Access-Control-Max-Age 1728000;
        add_header Content-Length 0;
        return 204;
    }

    proxy_pass http://backend;
}

```

### WebSocket 代理

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

    server {
        location /ws/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_read_timeout 3600s;  # WebSocket 长连接，加大超时
        }
    }
}

```

---

## 9\. 完整 FastAPI 部署配置

```nginx
# /etc/nginx/conf.d/fastapi.conf

upstream fastapi {
    server 127.0.0.1:8000;
    keepalive 32;  # 保持连接池
}

server {
    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;
    ssl_protocols TLSv1.2 TLSv1.3;

    # 安全头
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 文件上传大小限制
    client_max_body_size 10M;

    # API 文档（不限流）
    location ~ ^/(docs|redoc|openapi.json)$ {
        proxy_pass http://fastapi;
        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 https;
    }

    # API 接口（限流）
    location /api/ {
        limit_req zone=api burst=30 nodelay;
        proxy_pass http://fastapi;
        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 https;
        proxy_http_version 1.1;
        proxy_set_header Connection "";  # HTTP keepalive
    }

    # WebSocket
    location /ws/ {
        proxy_pass http://fastapi;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
    }
}

server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

```

---

## 10\. 前端 SPA 部署配置

```nginx
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/dist;
    index index.html;

    # SPA 路由：所有路径回退到 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源（Vite 构建的哈希文件名，永久缓存）
    location ~* \.(js|css|woff2?|ttf|eot|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 图片缓存
    location ~* \.(jpg|jpeg|png|gif|ico|webp)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

    # 接口代理（前后端同域，避免跨域）
    location /api/ {
        proxy_pass http://backend:8000/api/;
        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 https;
    }
}

```

---

## 11\. 常用命令

```bash
# 测试配置文件语法
nginx -t

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

# 优雅停止
nginx -s quit

# 强制停止
nginx -s stop

# 查看进程
ps aux | grep nginx

# Docker 中重载
docker exec nginx nginx -s reload
docker compose exec nginx nginx -s reload

```

---

## 12\. 踩坑与注意事项

### proxy\_pass 末尾斜杠的影响

```nginx
# 有斜杠：转发时去掉 location 前缀
location /api/ {
    proxy_pass http://backend/;
    # /api/users → http://backend/users
}

# 无斜杠：转发时保留 location 前缀
location /api/ {
    proxy_pass http://backend;
    # /api/users → http://backend/api/users
}

```

### add\_header 不能继承

子 location 块使用 `add_header` 后，父块的 `add_header` 会失效。需在每个 location 都添加，或使用 `headers-more-nginx-module` 模块。

### 配置修改后必须 reload

```bash
# 先测试语法，再重载
nginx -t && nginx -s reload

```

---

## 最佳实践

**每次修改配置前先 `nginx -t` 测试语法**：直接 reload 语法错误的配置会导致 Nginx 拒绝加载新配置（保留旧配置运行），但部分情况下会导致 worker 进程退出，服务中断。养成 `nginx -t && nginx -s reload` 的习惯。

**用 `include` 拆分配置文件**：把每个虚拟主机的 `server` 块拆到 `/etc/nginx/conf.d/` 或 `sites-enabled/` 目录下，主配置文件保持简洁，也方便用 Ansible / 脚本管理多站点。

```nginx
# nginx.conf
http {
    include /etc/nginx/conf.d/*.conf;
}

```

**代理后端时设置必要的 Header**：不传 `X-Real-IP` 和 `Host` 会导致后端看到的客户端 IP 是 Nginx 的 IP，以及 Host 不正确。

```nginx
location / {
    proxy_pass http://backend;
    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;
}

```

**静态文件用 `root` 而非 `alias`**：两者行为不同，`alias` 需要精确匹配 location 路径，用错会导致 404。静态文件优先考虑 `root`。

**开启 Gzip 压缩减少传输体积**：HTML/CSS/JS 文件 Gzip 后通常减少 60–80% 体积，对首屏性能影响显著。

```nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1024;
gzip_comp_level 6;

```

---

## 常见陷阱

### 陷阱：`proxy_pass` 末尾斜杠影响路径拼接

**现象：** `location /api/` 配置后，访问 `/api/users` 有时转发到 `http://backend/users`，有时是 `http://backend/api/users`，行为不一致。

**原因：** `proxy_pass` 末尾有无 `/` 决定是否保留 location 路径：

- `proxy_pass http://backend`（无斜杠）：保留完整 URI（`/api/users` → `/api/users`）
- `proxy_pass http://backend/`（有斜杠）：去掉 location 前缀（`/api/users` → `/users`）

**解决：** 明确选择语义，并与后端路由约定一致。

```nginx
# 转发包含 /api 前缀
location /api/ { proxy_pass http://backend; }    # /api/users → /api/users

# 去掉 /api 前缀再转发
location /api/ { proxy_pass http://backend/; }   # /api/users → /users

```

---

### 陷阱：`add_header` 只在当前 location 生效，子 location 不继承

**现象：** 在 `server` 块设置了 CORS header，但某个 `location` 内没有该 header。

**原因：** `add_header` 在子 location 块中不继承父级的 `add_header` 指令。子 location 只要有自己的 `add_header`，父级的全部失效。

**解决：** 在每个需要 header 的 location 块内都显式添加，或使用 `headers-more-nginx-module`（需要编译安装）。

```nginx
location /api/ {
    add_header Access-Control-Allow-Origin *;   # 必须在此重复声明
    proxy_pass http://backend/;
}

```

---

### 陷阱：WebSocket 代理不加 Upgrade header 导致连接失败

**现象：** 前端 WebSocket 连接到 Nginx 代理后报 `101 Switching Protocols` 失败，或 `1006 Connection closed abnormally`。

**原因：** WebSocket 升级需要在 HTTP/1.1 之上协商，Nginx 默认用 HTTP/1.0 和后端通信，且不传递 `Upgrade` header。

**解决：** 在 WebSocket location 块中设置 `proxy_http_version 1.1` 并传递 Upgrade 相关 header。

```nginx
location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade    $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;   # WebSocket 长连接，防止超时断开
}

```

---

## 参见

- [Docker Compose完全指南](https://blog.vercanti.com/docker-compose-wan-quan-zhi-nan/)
- [Docker初级指南](https://blog.vercanti.com/docker-chu-ji-zhi-nan/)
- [FastAPI完全指南](https://blog.vercanti.com/fastapi-wan-quan-zhi-nan/)
- [Kubernetes基础](https://blog.vercanti.com/kubernetes-ji-chu/)