目录
-
- [一、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 服务器 / 反向代理服务器。它在生产部署里通常干两件事:
- 静态托管 :把前端打包出来的
dist/文件直接返回给浏览器。 - 反向代理 :把
/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 |