‹ 返回笔记 Esc·

Nginx 问题与修复

基本结构 全局块:配置全局变量,如用户、进程数等,不设置会有默认值 events 块:配置与网络连接相关的选项,如连接数等,每个配置文件中只能有一个,不设置会有默认值 http 块:最常见的配置块,处…

基本结构

  • 全局块:配置全局变量,如用户、进程数等,不设置会有默认值
  • events 块:配置与网络连接相关的选项,如连接数等,每个配置文件中只能有一个,不设置会有默认值
  • http 块:最常见的配置块,处理 HTTP 请求的相关设置,包含 server 块和 location 块,每个配置文件中只能有一个,不设置会有默认值
  • upstream 块:定义一个后端服务器池,主要用于负载均衡

上面的块只能在 Nginx 主配置文件(通常是 /etc/nginx/nginx.conf)中定义,而不能在其他的配置文件中(如 sites-available 或 conf.d 目录中的文件)

  • server 块:用来配置虚拟主机,监听指定的 IP 地址和端口,处理不同的域名。每个配置文件中可以有多个
  • location 块:用来匹配不同的 URL 路径,可以精确匹配、前缀匹配或使用正则表达式
    • 精确匹配:使用 = 符号,表示完全匹配
    • 前缀匹配:默认方式,匹配前缀的路径
    • 正则表达式匹配:使用 ~~* 表示区分大小写的正则匹配
1# 全局块
2# 工作进程数量,对于多核处理器,建议与 CPU 核心数相同来调整该值
3worker_processes auto; #  自动检测 CPU 核心数
4# 指定 Nginx 进程的运行用户和用户组
5user www-data;
6# 指定 PID 文件路径
7pid /var/run/nginx.pid;
8# 允许包含其他配置文件,可以实现配置的模块化和重用
9# include /etc/nginx/conf.d/*.conf;
10
11events {
12    # 每个工作进程可以同时处理的最大连接数(默认 1024)
13    worker_connections 1024;
14    # 允许每个工作进程一次性接受多个连接,在高并发情况下可以提高性能
15    multi_accept on;
16    # 控制连接的接受方式,在多个工作进程之间共享,从而避免竞争条件,适用于连接频繁到来的场景
17    accept_mutex on;
18}
19
20http {
21    # 引入 MIME 类型文件,使 Nginx 能正确处理各种文件类型的响应
22    include mime.types;
23    # 设置默认的 MIME 类型,当 Nginx 无法识别文件类型时,使用这个默认类型
24    default_type application/octet-stream;
25    # 用于在文件传输时提高性能,允许直接通过操作系统的缓存发送文件,而不需要将文件读取到用户空间
26    sendfile on;
27    # 优化大文件的传输
28    tcp_nopush on;
29    # 低延迟响应
30    tcp_nodelay on;
31    # 设置客户端和服务器之间保持连接的时间(秒),如果在指定的时间内没有新的请求,将关闭连接
32    keepalive_timeout 65;
33    # 设置服务器向客户端发送响应的超时时间,如果客户端在指定时间内没有接收数据,将关闭连接
34    send_timeout 30;
35    # 关闭或开启在 HTTP 响应头中显示 Nginx 的版本信息(为了安全性,通常设置 off)
36    server_tokens off;
37    # 启用或禁用 gzip 压缩。开启后,Nginx 会对传输内容进行压缩,从而减少传输的数据量
38    gzip on;
39    # 限制客户端请求的最大请求体大小,防止大文件上传
40    client_max_body_size 1M;
41    # 访问日志(不配置就没有,不会自动删除,错误日志不配置有默认)
42    access_log /var/log/nginx/access.log main;
43
44    upstream backend {
45        # 允许每个连接最多处理 2 个请求(默认 1)提高性能
46        keepalive 2;
47        # 权重越大,优先级越高
48        server 127.0.0.1:8001 weight=3;
49        # 标记此服务器为不可用,通常用于在更新服务器配置时
50        server 127.0.0.1:8002 down;
51        # 备用服务器,只有主服务器都不可用的情况,才会将请求分配
52        server 127.0.0.1:8003 backup;
53        # 最大并发连接数被限制为10个,如连接数超过,则把请求转发到其他服务
54        server 127.0.0.1:8004 max_conns=10;
55        # 最少连接,优先将请求分发给当前连接数最少的服务器
56        least_conn;
57        # IP 哈希,根据客户端的 IP 地址进行请求分发,使同一个客户端总是访问同一台服务器
58        ip_hash;
59    }
60
61    server {
62        listen       80;  # 监听端口 80
63        server_name  example.com;  # 域名
64
65        location / {
66            root   /var/www/html;       # 设置根目录
67            index  index.html index.ht;  # 默认首页文件
68            try_files $uri @jump;
69        }
70        #    命名位置跳转 @
71        location @jump {
72            proxy_pass http://backend;
73            proxy_http_version 1.1;
74            proxy_set_header Upgrade $http_upgrade;
75            proxy_set_header Connection $connection_upgrade;
76        }
77        # 精确匹配 =
78        location = /login {
79            # 反向代理到后端服务
80            proxy_pass http://backend;
81            proxy_set_header Host $host;
82            proxy_set_header X-Real-IP $remote_addr;
83            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
84            proxy_set_header X-Forwarded-Proto $scheme;
85        }
86        # 前缀匹配 /
87        location /api/ {
88            allow 192.168.1.0/24;  # 允许指定 IP 段
89            deny all;  # 拒绝其他访问
90        }
91        # 正则表达式匹配
92        location ~* \.(jpg|jpeg|png|gif|ico)$ {
93            root /var/www/images;
94            expires 30d;  # 缓存时间
95        }
96        # 自定义错误页面
97        error_page 500 502 503 504 /50x.html;
98        location = /50x.html {
99            root /var/www/html;
100        }
101        # 301 永久重定向
102        location /oldpath {
103            return 301 /newpath;
104        }
105        # 302 临时重定向
106        location /temp {
107            rewrite ^/temp$ /newpath redirect;
108        }
109    }
110    # 配置 SSL 证书并启用 HTTPS
111    server {
112      listen 443 ssl;
113      server_name secure.example.com;
114      ssl_certificate /etc/nginx/ssl/nginx.crt;
115      ssl_certificate_key /etc/nginx/ssl/nginx.key;
116      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
117      ssl_ciphers HIGH:!aNULL:!MD5;
118    }
119}

目录选择偏好

单独的配置文件:/etc/nginx/conf.d/zailiangs.com.conf

禁用则尾缀加 .disabled

SSL 证书:/etc/nginx/ssl/zailiangs.com.key


Nginx 目录权限

方案一:改所有者

1sudo chown -R zailiang:zailiang /etc/nginx/conf.d
2sudo chown -R zailiang:zailiang /etc/nginx/ssl
3# 查看
4ls -ld /etc/nginx

方案二:保留 root 所有权

如果你希望 /etc/nginx 下面所有东西都保持 root 管理:

1sudo chown root:zailiang /etc/nginx
2sudo chmod 775 /etc/nginx

这样:

  • root 完全控制
  • zailiang 可以上传、修改文件

SSL 证书权限建议

1sudo chmod 644 /etc/nginx/ssl/*.crt
2sudo chmod 600 /etc/nginx/ssl/*.key

403 Forbidden

确保 Nginx 的运行用户对文件有正确的读取权限。Nginx 默认的用户是 nginx 或 www-data(取决于操作系统)。你可以检查一下/usr/share/nginx/html/blog/和 Nginx 配置中的其他路径的权限。

使用以下命令检查文件和目录权限:

1ls -l /usr/share/nginx/html/blog/

检查目录的权限,确保它至少是 755(目录必须可执行才能让 Nginx 访问它):

1sudo chmod -R 755 /usr/share/nginx/html/blog/

部署防止根域名报证书有误

证书申请时填根域名不带 www nginx 的 server_name 可以填多个

1server {
2  listen 443 ssl;
3  server_name zailiangs.com www.zailiangs.com;
4  ssl_certificate /etc/nginx/cert/zailiangs.com/zailiangs.com.pem;
5  ssl_certificate_key /etc/nginx/cert/zailiangs.com/zailiangs.com.key;
6  ssl_session_cache shared:SSL:1m;
7  ssl_session_timeout 5m;
8  ssl_protocols TLSv1.2;
9  ssl_ciphers HIGH:!aNULL:!MD5;
10  ssl_prefer_server_ciphers on;
11
12  location / {
13    root   html;
14    index  index.html index.htm;
15    proxy_pass  http://zailiangs;
16    proxy_redirect default;
17  }
18}

语法报错

1(base)   ~ nginx -t
2nginx: [emerg] "events" directive is not allowed here in /etc/nginx/conf.d/milvus.conf:3
3nginx: configuration file /etc/nginx/nginx.conf test failed
4(base)   ~ nginx -t
5nginx: [emerg] "http" directive is not allowed here in /etc/nginx/conf.d/milvus.conf:3
6nginx: configuration file /etc/nginx/nginx.conf test failed

events http 块只能在 Nginx 主配置文件(通常是 /etc/nginx/nginx.conf)中定义,而不能在其他的配置文件中(如 sites-available 或 conf.d 目录中的文件)


root 与 alias 区别

root 会将匹配的 location 路径保留并拼接到指定的根目录路径后。

1location /way {
2    root /usr/share/nginx/html;
3    index index.html;
4}
5# root 将匹配的 location 路径拼接 /usr/share/nginx/html + /way
6# 无需以 / 结尾
7# /root_path/location_path/request_path

alias 用于替换匹配的路径,与 root 不同,alias 不会拼接 location 中的路径,而是直接替换整个路径。

1location /test-way {
2    alias /usr/share/nginx/html/way/;
3    index index.html;
4}
5# /test-way 会映射到 /usr/share/nginx/html/way/ 这个目录下
6# 必须以 / 结尾
7# /alias_path/request_path

/etc/nginx/sites-enabled/default 的作用

这个文件定义了一个默认的网站(虚拟主机),当用户访问 Nginx 服务器的 默认 IP 地址 + 端口(比如 http://192.168.2.42)时,如果没有其他匹配的 server_name,就会由这个配置来响应。

1server {
2    listen 80 default_server;
3    root /var/www/html;
4    index index.html index.htm;
5}

如果用户没有请求特定域名或端口匹配不到其他 server 块时,Nginx 会使用这个默认配置来处理请求。 这个文件有什么“副作用”? 如果你手动在 /etc/nginx/nginx.conf 或其他 conf.d 中写了你自己的网站配置,但没有删除这个 default 配置文件,就可能遇到以下问题:

  1. 你的网站运行在端口 8000,而访问 80 时看到的却是默认页面 原因:default 配置还在监听 80,导致访问 http://ip 显示的是默认页面而不是你的 Vue 页面。
  2. 端口冲突问题 如果你手动写了一个 listen 80 的配置,而 default 配置也有 listen 80 default_server,可能会导致 Nginx 重启失败或启动错误。
  3. default_server 抢占默认站点位置 会影响你设置的某些虚拟主机无法生效(因为 default 被优先使用了)。

大模型流式推送卡成一大块发送

在使用 Nginx 作为 SSE(Server-Sent Events)反向代理时,数据被“卡成一大块”发送,并非逐字符平滑流出,往往与 Nginx 的 缓冲机制 有关,而非 SSE 本身问题。

1location /sse {
2    proxy_pass http://backend;
3    proxy_http_version 1.1;            # 开启 HTTP/1.1 支持
4    proxy_set_header Connection "";    # 清除 Connection 头,保持连接
5    proxy_buffering off;              # 关闭缓冲,立即推送
6}
  • 若后端已支持 X‑Accel‑Buffering: no,则可移除 proxy_buffering off;,由响应头控制缓冲策略。

去除响应头 Server 的版本号

1vim /etc/nginx/nginx.conf
2
3http {
4    server_tokens off;
5    ...
6}
7
8sudo nginx -s reload

这会将 Server: nginx/1.24.0(Ubuntu) 改为 Server: nginx


修改请求头 Referer 不允许从其他地方的请求

1set $referer_check 1;
2
3location /nt-rest {
4    set $referer_valid 0;
5    if ($http_referer ~* "^https?://(127\.0\.0\.1:8080|localhost:8080|192\.168\.2\.42:8080)") {
6        set $referer_valid 1;
7    }
8    # 组合判断:referer_check=1 且 referer 无效
9    set $deny "${referer_check}${referer_valid}";
10    if ($deny = "10") {
11        add_header Content-Type application/json;
12        return 403 '{"code":403,"msg":"illegal referer"}';
13    }
14    proxy_pass  http://nt-rest;
15}

正则转义:. 需要写成 .,例如 192.168.1.100

协议匹配:^https?:// 同时匹配 http:// 和 https://

端口匹配:使用 :\d+ 匹配任意端口,或写死端口如 :5173

测试配置:修改后执行 nginx -t 测试,然后 nginx -s reload 重载