nginx配置作用域严格分main、server、location三层,指令有效性取决于其允许出现的位置及继承类型:normal可继承覆盖,array下层替换上层,action不继承,context-only仅限特定层级。

Nginx 的配置作用域不是“写在哪都生效”,而是严格按层级划分的执行边界。理解它,关键在于明白指令只在它被允许出现的位置才有效,且不同层级之间存在明确的继承与覆盖规则。
三个核心作用域:Main、Server、Location
这是 Nginx 配置的骨架结构,自外向内嵌套:
-
Main(全局块):最外层,不被任何大括号包裹。在这里设置的指令影响整个 Nginx 进程,比如
user、worker_processes、error_log、pid。它还包含events和http两个子块。 -
Server(虚拟主机块):位于
http块内,用server { ... }包裹。每个server定义一个独立的虚拟主机,响应特定的域名或 IP+端口组合。常用指令如listen、server_name、root、access_log都在此层级生效。 -
Location(路径匹配块):嵌套在
server内,用location [modifier] /path { ... }定义。它针对请求 URI 路径做精细化控制,比如静态资源托管、反向代理转发、权限限制等。典型指令有proxy_pass、try_files、alias。
指令不是“自动继承”,而是分类型处理
同一指令出现在不同层级,效果完全不同——不是简单“子级覆盖父级”,而是取决于指令自身的继承类型:
-
Normal 类型(如 root、index):支持继承,低层可覆盖高层。例如
server里设了root /var/www,location /api里又写了root /opt/backend,那么访问/api/xxx就会从/opt/backend下找文件。 -
Array 类型(如 access_log):下层定义会完全替换上层,不合并。如果
http块启用了日志,但某个location显式写access_log off;,那该路径就彻底不记访问日志。 -
Action 类型(如 proxy_pass、rewrite):不继承。必须显式写在需要生效的
location或server中,上级写的proxy_pass对子location没有任何影响。 -
Context-only 类型(如 listen、server_name):只能出现在特定层级。比如
listen只能在server块里用,写在http或location中会直接报错。
变量和指令的可用性也受作用域限制
不是所有变量在所有地方都能用,也不是所有指令在哪都能赋值:
- 内置变量(如
$host、$request_uri)只能读,不能改;它们在大多数上下文都可用,但某些阶段(如日志写入前)可能尚未生成,导致为空。 - 用
set、map定义的自定义变量,必须在能执行该指令的上下文中使用——set允许在server和location,但不能在http块顶层直接用(除非配合map)。 - 像
return、rewrite这类动作指令,通常只在server或location中有意义,在http块里写会语法错误。
配置块嵌套关系决定实际执行顺序
一个请求进来后,Nginx 不是线性读配置,而是按树状结构逐级匹配:
- 先匹配
http→ 找到对应server(靠listen+server_name)→ 再匹配location(按最长前缀或正则优先级)。 - 只有最终选中的
location块里的指令才会真正参与本次请求处理;同级其他location、上级未被继承的指令,都不起作用。 - 这意味着,即使你在
http块里写了proxy_set_header,若没在具体location中调用proxy_pass,这条头设置就只是“闲置”而已。











