我的Nginx 的配置分析
一. 如何确定当前服务器有哪些Nginx配置
两个问题:
- 当前机器的主配置入口是哪个文件?
- 最终加载了哪些conf.
确认主入口文件:
nginx -V 2>&1 | grep -oE -- '--conf-path=[^ ]+'
--conf-path=/etc/nginx/nginx.conf
打开文件后查看 include /etc/nginx/modules-enabled/*.conf; 有这么一行.
然后继续查看有这个地方引入了哪些文件
ls -lah /etc/nginx/sites-enabled
lrwxrwxrwx 1 root root 36 Jan 15 11:22 card-game -> /etc/nginx/sites-available/card-game
lrwxrwxrwx 1 root root 38 Jan 20 08:58 zhangrh.top -> /etc/nginx/sites-available/zhangrh.top
readlink -f /etc/nginx/sites-enabled/*
/etc/nginx/sites-available/card-game
/etc/nginx/sites-available/zhangrh.top
这里可以看到, 我们饮用了两个地址的配置 分别是card-game, zhangrh.top.
二. 分析我的Nginx配置
# /etc/nginx/sites-available/zhangrh.top
# -----------------------------
# HTTP -> HTTPS
# -----------------------------
server {
listen 80; # 监听80端口 也就是http
server_name zhangrh.top www.zhangrh.top; # 这个server处理的域名, 只有host匹配域名, 才会走这个server
location / { # / 是前缀匹配, 匹配所有的路径
return 301 https://$host$request_uri; # 直接301重定向, $host是请求的Host, $request_uri原始路径+query
}
}
# -----------------------------
# HTTPS
# -----------------------------
server {
# 监听443端口(https), ssl: 启用TLS.
# http2: 开启HTTP/2(访问静态资源更快)
# websocket依旧是Http1.1/upgrade
listen 443 ssl http2;
server_name zhangrh.top www.zhangrh.top;
# TLS证书文件pem, 私钥文件key
ssl_certificate /etc/nginx/ssl/zhangrh.top.pem;
ssl_certificate_key /etc/nginx/ssl/zhangrh.top.key;
# -----------------------------
# Tracking endpoint: /t or /t/
# -----------------------------
# location ~: 正则匹配locaton
# ^开头 /t匹配 /?可选一个/ $结尾, 所以只能匹配/t, /t/
location ~ ^/t/?$ {
# 这个location的访问日志写到指定目录
# track 是一个log_format名称, 在http{}全局中定义过
access_log /var/log/nginx/track.log track;
# 不添加缓存
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always;
# 兼容旧行为, always 即使是204/4xx/5xx也加入状态码, 这些默认不加
add_header Pragma "no-cache" always;
# 返回204 No Conent(无响应体)
return 204;
}
# -----------------------------
# Verify file: direct access
# -----------------------------
# 微信验证文件
# location =: 精确匹配, 只能访问这个路径
location = /3ddb389bdb8ab254c1b8ede286ec0f08.txt {
# 这个location的请求根目录, 请求路径会拼到这个后面形成实际的文件路径
root /var/www/card-game-site.new;
default_type text/plain; # 没有扩展名, / 类型不明确时, 默认响应text/plain
try_files /3ddb389bdb8ab254c1b8ede286ec0f08.txt =404; # 按照这个顺序找文件, 没有的话404
}
# -----------------------------
# Root redirect to blog
# -----------------------------
# 根目录直接跳转到博客
# 这里是相对路径跳转, host保持不变
location = / {
return 301 /20250122_website/;
}
# -----------------------------
# API -> backend (include WebSocket)
#
# IMPORTANT:
# - Keep original path (NO rewrite).
# - Your WS URLs are:
# /api/20250120_card-game01/ws
# /api/20250126-card_game02/ws
# So upstream will receive the same path.
# -----------------------------
# api开始反向代理, ^~ 一旦匹配这个前缀, 后面的正则location就不能用了, 保护/api的优先级
location ^~ /api/ {
access_log /var/log/nginx/api_ws.log;
# 请求转发到当前机器的3001端口
#没有尾部/, 转发时保持原样
# /api/xxx => upstream 仍然是/api/xxx 对ws路径关键
proxy_pass http://127.0.0.1:3001;
# 代理到upstream时, 使用http/1.1
# websocket 升级依赖http/1.1的upgrade机制, 所以是1.1
proxy_http_version 1.1;
# websocket upgrade (also ok for normal http)
# Upgrade: 客户端的Upgrade头传给upstream
# Connection: 告诉upstream这是升级链接
proxy_set_header Upgrade $http_upgrade;
# $connection_upgrade来自全局map, 用来在有upgarde时, 设置为upgarde. 否则close
proxy_set_header Connection $connection_upgrade;
# 原始host转发
proxy_set_header Host $host;
# 真实客户端ip
proxy_set_header X-Real-IP $remote_addr;
# 客户端ip追加到XFF列表, (多层代理, 保持路径)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 告诉后端原始请求是什么 http / https
proxy_set_header X-Forwarded-Proto $scheme;
# 读写超过1小时, 就关闭. 对长链接很重要
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
# -----------------------------
# Static assets cache: /<project>/static/...
# -----------------------------
# 静态资源匹配
location ~ "^/([A-Za-z0-9_-]+)/static/" {
root /var/www/card-game-site.new;
# 允许真实存在的文件访问, 否则直接404.
try_files $uri =404;
access_log off;
# 浏览器缓存30天
expires 30d;
}
# -----------------------------
# Add trailing slash: /<project> -> /<project>/
# -----------------------------
location ~ "^/([A-Za-z0-9_-]+)$" {
return 301 /$1/;
}
# -----------------------------
# SPA fallback (two-level): /<project>/<entry>/... -> /<project>/<entry>.html
#
# FIX:
# - add "=404" to stop internal redirect cycle when fallback file doesn't exist
# -----------------------------
# 两级spa回退
location ~ "^/([A-Za-z0-9_-]+)/([A-Za-z0-9_-]+)(?:/.*)?$" {
root /var/www/card-game-site.new;
try_files $uri $uri/ /$1/$2.html =404;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
# -----------------------------
# SPA fallback (project root): /<project>/... -> /<project>/index.html
#
# FIX:
# - add "=404" to stop internal redirect cycle when fallback file doesn't exist
# -----------------------------
# 项目根spa回退.
location ~ "^/([A-Za-z0-9_-]+)/" {
root /var/www/card-game-site.new;
try_files $uri $uri/ /$1/index.html =404;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
# -----------------------------
# Default: deny other root paths
# -----------------------------
location / {
return 404;
}
}
三. 不懂的点:
- ssl:启用 TLS什么意思?
- listen 443 ssl;表示这个端口的链接不再是明文http. 先做一层TLS握手/加密
- 浏览器连到zhangrh.top: 443, 先校验证书, 协商加密孙法, 建立加密通道
- 通道建立以后, 浏览器在这个加密通道发送http请求
- location ^~ /api/ 能写成 location ~ ^/api/吗?
- 技术上能写, 但是^~ 表示的是强位优先级, 不再去看后面的正则location
- ~ ^/api/: 会参与正则location竞争, 如果有更靠前的正则会被抢走
- 会被其他的比如项目上的html正则误匹配
- $http_upgrade;啥意思
- $http_xxx表示: 客户端里请求头是xxx值
- $connection_upgrade来自全局map, 用来在有upgarde时, 设置为upgarde. 否则close, 这个没有理解, 这是一个转发也就是ng收到这个请求, 然后转发到3001, 那长链接, 是首先浏览器和ng建立, 然后ng再和3001端口建立吗?
- 两段连接是独立的.
- 浏览器请求WebSocket时, Ng也需要发起WebSocket请求
- 普通Api没有Upgrade头, 如果强行发Connection: upgrade会被误会, 所以全局用一个map生成变量 $connection_upgrade;
- 如果有$http_upgrade时, $connection_upgrade 就时upgrade
- 如果没有, 就是close
- location ~ 这种是不是一直向下匹配
- 先看location =
- 在看location /xxx
- 如果最长匹配时 ^~ 就用这个, 停止匹配
- 按照顺序检查政策 location ~, 第一个正则
- 没有任何正则 用第二步找到最长前缀
- 不会匹配多个, 只有一个最终location
- /
-> / / 这个是不是不用也行, 感觉其他网站都不会这么用. - 如果全部用绝对路径引用资源
- 要么框架, 构建构建帮忙处理base path
- 要么服务端路由, 不靠静态相对路径
- 那我后面检查了我的frontend 这个工程, 确认了路径即可 保证资源路径都是绝对路径
- proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; 和proxy_set_header Connection $connection_upgrade;这一行的区别?- 不能合并, 因为是两个不同的key, 导致的不同的value
- 合并指的是$connection_upgrade能代表两个值.

浙公网安备 33010602011771号