Nginx 原理与配置 —— 通用指南

目录

    • [一、nginx 是什么](#一、nginx 是什么)
      • [反向代理 vs 正向代理(容易混)](#反向代理 vs 正向代理(容易混))
    • [二、Ubuntu 下 nginx 的安装与目录结构](#二、Ubuntu 下 nginx 的安装与目录结构)
    • [三、软连接机制 ------ nginx 站点启用的核心](#三、软连接机制 —— nginx 站点启用的核心)
    • [四、配置文件结构:server / location / server_name](#四、配置文件结构:server / location / server_name)
      • [4.1 server_name ------ 多站点靠域名分流的关键](#4.1 server_name —— 多站点靠域名分流的关键)
      • [4.2 location ------ 路径匹配规则](#4.2 location —— 路径匹配规则)
      • [4.3 proxy_pass ------ 反向代理 + 结尾斜杠的坑](#4.3 proxy_pass —— 反向代理 + 结尾斜杠的坑)
      • [4.4 透传请求头](#4.4 透传请求头)
      • [4.5 try_files ------ SPA history 模式必备](#4.5 try_files —— SPA history 模式必备)
    • [五、HTTPS 配置](#五、HTTPS 配置)
      • [5.1 证书从哪来](#5.1 证书从哪来)
      • [5.2 证书文件](#5.2 证书文件)
      • [5.3 HTTPS server 块写法](#5.3 HTTPS server 块写法)
      • [5.4 HTTP → HTTPS 301 跳转](#5.4 HTTP → HTTPS 301 跳转)
    • 六、常用调试与维护命令

一、nginx 是什么

nginx 是一个 Web 服务器 / 反向代理服务器。它在生产部署里通常干两件事:

  1. 静态托管 :把前端打包出来的 dist/ 文件直接返回给浏览器。
  2. 反向代理 :把 /api 这类请求转发给后端应用进程(比如 uvicorn、gunicorn、Node 服务)。

它本身不跑你的业务代码,只负责"接客、分发、转交"。

反向代理 vs 正向代理(容易混)

类型 代理谁 谁知道它存在 典型场景
正向代理 代理客户端 服务端不知道真实客户端 翻墙、爬虫 IP 池
反向代理 代理服务端 客户端不知道真实后端 nginx 转发到 uvicorn

二、Ubuntu 下 nginx 的安装与目录结构

Ubuntu / Debian 用 apt 安装:

bash 复制代码
sudo apt update && sudo apt install -y nginx

装完之后这些路径是固定的:

路径 作用 一般要不要动
/usr/sbin/nginx 主程序二进制 不动
/etc/nginx/nginx.conf 主配置文件(全局) 一般不动,里面 include 下面两个目录
/etc/nginx/sites-available/ 可用站点目录(实体配置文件存这) 在这里新建/编辑站点配置
/etc/nginx/sites-enabled/ 已启用站点目录(只放软连接) 用软连接控制启用谁
/etc/nginx/conf.d/ 另一种站点配置目录(部分发行版用这个) 看主配置 include 的是哪个
/var/log/nginx/ 日志:access.log、error.log 看日志用
/run/nginx.pid 主进程 PID 不用管

Ubuntu 默认 nginx.conf 里有一句 include /etc/nginx/sites-enabled/*;,所以 nginx 启动时只会读 sites-enabled/ 下的文件,不读 sites-available/。


三、软连接机制 ------ nginx 站点启用的核心

sites-available/ 和 sites-enabled/ 之间靠 符号链接(symlink,软连接) 关联,这是 nginx 站点管理的标准玩法。

原理图

复制代码
你写的真实配置文件
   /etc/nginx/sites-available/my-site          ← 实体文件,内容在这
                          │
                          │  ln -s 建立软连接
                          ▼
   /etc/nginx/sites-enabled/my-site  ────────► (指向左侧实体文件)
                          │
                          │  nginx.conf: include /etc/nginx/sites-enabled/*;
                          │  所以 nginx 只看 sites-enabled 下的文件
                          ▼
                   nginx 加载这份配置 → 生效

为什么要分两个目录

  • sites-available/ 是仓库:所有写过的站点配置都存这里,删了就没了。
  • sites-enabled/ 是开关 :里面只放指向 available 的软连接。有软连接 = 启用,删软连接 = 停用(实体文件还在 available,没丢)。

好处:不用删配置文件,只"删软连接 / 建软连接"就能开关站点,特别适合临时下线维护、多项目并存场景。

标准命令

bash 复制代码
# 启用一个站点(建软连接)
sudo ln -s /etc/nginx/sites-available/my-site /etc/nginx/sites-enabled/my-site

# 停用一个站点(只删软连接,实体文件保留)
sudo rm /etc/nginx/sites-enabled/my-site

# 改完任何配置后:先测语法,再重载(不中断服务)
sudo nginx -t
sudo systemctl reload nginx

四、配置文件结构:server / location / server_name

一份站点配置长这样(骨架):

bash 复制代码
server {
    listen 80;                  # 监听端口
    server_name example.com;    # 匹配哪个域名

    root /var/www/dist;         # 静态文件根目录
    index index.html;

    location /api/ {            # 路径匹配块
        proxy_pass http://127.0.0.1:8000;   # 反代到后端
    }

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

4.1 server_name ------ 多站点靠域名分流的关键

nginx 一个进程能管多个 server 块,靠 server_name(域名)决定"这个请求给谁"。这是虚拟主机的核心:

bash 复制代码
浏览器请求 http://app.example.com/
        │
        ▼
   nginx (80端口) 收到请求
        │
        │  看请求头里的 Host 字段 = app.example.com
        │  在所有 server 块里找 server_name 匹配的
        ▼
   命中 server_name app.example.com 的那个块 → 走它的配置

所以同一台服务器、同一个 80 端口,可以同时承载 a.example.com、b.example.com、c.example.com 三个完全独立的站点,互不干扰。

server_name _(下划线) 是个特殊用法:_ 不会匹配任何真实域名,作为兜底默认 server。当请求的域名没匹配上任何 server 块时,nginx 把请求扔给它。单站点时代常用,多站点时不推荐依赖它。

4.2 location ------ 路径匹配规则

location 决定"URL 路径走哪条路"。匹配优先级(从高到低):

类型 写法 说明
精确匹配 location = /xxx 完全相等才命中,优先级最高
前缀(长) location ^~ /assets/ 前缀匹配,命中后不再查正则
正则 location ~* \.png$ 正则匹配,~* 不区分大小写,~ 区分
前缀(普通) location /api/ 普通前缀匹配,优先级最低

典型组合:/api/ 反代后端、/assets/ 静态缓存、/ 兜底返回 index.html。

4.3 proxy_pass ------ 反向代理 + 结尾斜杠的坑

bash 复制代码
location /api/ {
    proxy_pass http://127.0.0.1:8000;     # 结尾不带斜杠
}

结尾带不带斜杠,行为完全不同,这是 nginx 最经典的坑:

proxy_pass 写法 转发给后端的路径 后端路由该写成
http://127.0.0.1:8000;(不带斜杠) 原样保留 /api/xxx /api/xxx
http://127.0.0.1:8000/;(带斜杠) 剥掉 /api/ 前缀,变成 /xxx /xxx

记忆口诀:proxy_pass 带 URI(带斜杠)= 替换;不带 URI = 原样转发。前后端路由前缀必须对齐这个行为,否则一定 404。

4.4 透传请求头

反代时后端默认拿不到客户端真实 IP,要手动透传:

nginx 复制代码
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;
  • Host:原始域名。
  • X-Real-IP:客户端真实 IP(否则后端看到的是 nginx 的 127.0.0.1)。
  • X-Forwarded-For:IP 链路。
  • X-Forwarded-Proto:原始协议 http/https(后端要知道是不是 HTTPS 才能生成正确的回调 URL)。

4.5 try_files ------ SPA history 模式必备

Vue/React 用 history 路由模式时,前端 URL 是 http://域名/result/123,但服务器上根本不存在 /result/123 这个文件,直接刷新会 404。

复制代码
location / {
    try_files $uri $uri/ /index.html;
}

含义:先按完整路径找文件($uri),再当目录找($uri/),都找不到就返回 index.html。这样所有非静态文件请求都回退到前端入口,由前端路由器在浏览器里解析。这是 SPA 的标准写法。


五、HTTPS 配置

5.1 证书从哪来

三种主流来源:

来源 工具 特点
Let's Encrypt certbot 免费、自动续期、命令行管理,路径在 /etc/letsencrypt/live/域名/
腾讯云/阿里云免费证书 控制台申请下载 免费、有效期 1 年、到期需手动续、下载 zip 上传到服务器
商业付费证书 各 CA 厂商 付费、有 OV/EV 验证

腾讯云免费证书的关键限制 :一张证书只覆盖申请时填的域名(可带 www)。子域名不通用 ,每个子域名要单独申请一张证书。如果要用一张证书覆盖所有子域名,需要 通配符证书 (*.example.com),腾讯云免费证书不支持,需付费购买。

5.2 证书文件

Nginx 用的证书通常是两个文件:

文件 内容
fullchain.pem 或 xxx_bundle.crt 证书链(域名证书 + 中间证书),nginx 用 ssl_certificate 指向它
privkey.pem 或 xxx.key 私钥,nginx 用 ssl_certificate_key 指向它

腾讯云下载的 Nginx 格式 zip 里,对应的就是 xxx_bundle.crt 和 xxx.key。

5.3 HTTPS server 块写法

复制代码
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

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

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

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

5.4 HTTP → HTTPS 301 跳转

用户习惯输入 http://,要自动跳到 https://。单独写一个 80 端口的 server 块干这事:

复制代码
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;    # 永久重定向到 HTTPS
}

这样访问 http://example.com/xxx 会自动跳 https://example.com/xxx。


六、常用调试与维护命令

bash 复制代码
# 测试配置语法(改完必跑,不报错才 reload)
sudo nginx -t

# 重载配置(不中断服务,平滑生效)
sudo systemctl reload nginx

# 重启 nginx(万不得已用,会瞬断)
sudo systemctl restart nginx

# 查看状态
sudo systemctl status nginx

# 看错误日志(排查 404/502/配置问题第一手资料)
sudo tail -50 /var/log/nginx/error.log

# 看访问日志
sudo tail -50 /var/log/nginx/access.log

# 实时跟踪日志(Ctrl+C 退出)
sudo tail -f /var/log/nginx/error.log

排错思路

现象 排查方向
nginx -t 报错 配置语法问题,按错误行号定位
浏览器 502 Bad Gateway 后端进程没起 / 端口错 / 后端崩了,查 journalctl -u 后端服务名
浏览器 404 root 路径错 / dist 没 build / try_files 没配
接口 404 proxy_pass 结尾斜杠配错 / 后端路由前缀不匹配
HTTPS 证书报红 证书域名不匹配(覆盖范围)/ 证书过期 / 证书链不全
静态资源 403 nginx worker(www-data)对 dist 目录无读权限,或父目录无 o+x

相关推荐
Ruiery1 小时前
Linux 6.6内核 CPU 深度解析(四):中断与 IPI — 一个 CPU 怎么“喊“另一个 CPU
linux·运维·服务器
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-Nginx概述与源码编译安装
java·开发语言·nginx
志栋智能2 小时前
安全超自动化如何支持快速安全扩容?
运维·服务器·数据库·架构·自动化
承渊政道5 小时前
星空组网+Python实战:在另一台电脑上查看CSV报表
运维·开发语言·python·csv·星空组网
木卫二号Coding10 小时前
推荐Linux统计文件大小并操作删除工具-ncdu
linux·运维·服务器
志栋智能11 小时前
超自动化运维:实现IT服务消费化的基础
运维·自动化
198******1263411 小时前
2026企业AI办公工具选型指南:从评估框架到场景适配
大数据·运维·人工智能
吴声子夜歌11 小时前
Nginx应用与运维——Nginx HTTP模块详解(数据处理功能模块)
运维·nginx·http
2601_9672127211 小时前
专利型电源轨道系统技术路线对比与选型框架
大数据·运维·网络·经验分享