server 块与虚拟主机
上一篇我们看过 nginx.conf 的整体结构,知道 http 块里会嵌套若干个 server 块。这一章我们深入 server 块——它代表一个虚拟主机,是 Nginx 区分"不同站点"的核心机制。一台机器通过 server 块的巧妙组合,可以同时服务几十、几百个域名。
1. 一个最基础的 server 块
先看一个能跑起来的最小配置,理解每个指令的作用:
# 最基础的 server 块
server {
listen 80; # 监听 80 端口(HTTP 默认)
server_name example.com; # 匹配的域名
root /var/www/example; # 网站根目录
index index.html; # 默认首页文件名
location / {
# 这里暂时留空,root 和 index 已在 server 层定义
try_files $uri $uri/ =404;
}
}这个 server 监听 80 端口,匹配域名 example.com,把请求映射到 /var/www/example 目录。这一节我们先理解四个核心指令:listen、server_name、root、index。
2. listen:监听哪个端口
listen 决定 Nginx 在哪个网络端口/IP 上等连接。常见写法:
# listen 指令的几种写法
server {
listen 80; # 监听所有网卡的 80 端口
listen 127.0.0.1:80; # 只监听 127.0.0.1(本机访问)
listen 8080; # 监听非标准端口
listen 443 ssl; # 监听 443,并启用 SSL(HTTPS)
listen 443 ssl http2; # 同时启用 HTTP/2
listen [::]:80; # IPv6 监听
listen 80 default_server; # 标记为"默认 server"(兜底)
}
# default_server 的作用:当 Host 头不匹配任何 server_name 时,
# 请求会被发到 default_server 标记的那个 serverdefault_server 是个高频面试题:当请求的 Host 头不匹配任何 server_name 时,请求会被发到标记为 default_server 的那个 server。这个机制常用来拦截"恶意域名指向"——给 default_server 返回 444(无响应关闭连接)。
3. server_name:匹配哪个域名
server_name 是 Nginx 区分多站点的核心——通过 HTTP 请求头里的 Host 字段,Nginx 把请求路由到对应的 server 块:
# server_name 支持多种匹配形式
server {
listen 80;
server_name example.com; # 精确匹配
}
server {
listen 80;
server_name *.example.com; # 通配符(匹配 www.example.com、api.example.com 等)
}
server {
listen 80;
server_name www.example.org ~^www\d+\.example\.org$; # 正则(前面加 ~)
}
server {
listen 80 default_server;
server_name _; # 下划线是常用"无效域名"占位符,配合 default_server 兜底
}
# 匹配优先级(高到低):
# 1. 精确匹配 example.com
# 2. 前缀通配 *.example.com
# 3. 后缀通配 www.example.*
# 4. 正则匹配 ~^...$
# 5. default_server 兜底记住优先级口诀:精确 → 通配 → 正则 → 兜底。
几个常见坑:
- 本地测试想用域名?改
/etc/hosts加一行127.0.0.1 example.com。 - 正则里的小括号
(...)可以在配置里用$1引用(和 location 配合做路径重写)。 - 未配置 server_name 的请求会被发到第一个 server 或 default_server。
4. 三种虚拟主机类型
"虚拟主机"(Virtual Host)就是一台物理机伪装成多台服务器的技术。Nginx 支持三种区分方式:
# === 基于域名的虚拟主机(最常用)===
# 一台机器一个 IP,靠 Host 头分发到不同站点
server {
listen 80;
server_name siteA.com;
root /var/www/siteA;
}
server {
listen 80;
server_name siteB.com;
root /var/www/siteB;
}
# === 基于端口的虚拟主机 ===
# 同一域名,不同端口
server {
listen 8000;
server_name example.com;
root /var/www/app1;
}
server {
listen 8001;
server_name example.com;
root /var/www/app2;
}
# === 基于 IP 的虚拟主机 ===
# 服务器有多个网卡/IP
server {
listen 192.168.1.10:80;
server_name siteA.com;
}
server {
listen 192.168.1.11:80;
server_name siteB.com;
}实际生产中,基于域名的虚拟主机占 99%——因为它不需要多 IP,也不需要让用户输入端口号。
5. root 与 index
这两个指令决定"请求路径如何映射到磁盘文件":
# root 指令:把 URI 拼到 root 后面查找文件
server {
root /var/www; # server 层定义 root
location /images/ {
# root 会被继承:访问 /images/cat.png → /var/www/images/cat.png
}
location /static/ {
root /data; # 覆盖:访问 /static/app.js → /data/static/app.js
}
}
# index 指令:访问目录(URI 以 / 结尾)时按顺序尝试的默认文件
server {
index index.html index.htm index.php;
# 访问 / 会依次尝试 index.html → index.htm → index.php
}
# 注意:index 只在 URI 以 / 结尾时生效,对具体文件请求(/foo.html)无效一个高频混淆点:root 和 alias 的区别。简单说,root 是把 URI 整个拼到路径后面(/images/cat.png → /var/www/images/cat.png),而 alias 是替换匹配部分。这个区别我们在 location 章节会详细对比。
6. error_page:自定义错误页
默认的 Nginx 错误页很丑,对用户体验不好。用 error_page 可以把 404、500 等状态码指向自定义页面:
# 自定义错误页(用户体验必备)
server {
error_page 404 /404.html; # 404 时返回站点根目录下的 404.html
error_page 500 502 503 504 /50x.html; # 所有 5xx 错误统一页面
error_page 403 https://example.com/forbidden; # 也可以跳转外部 URL
location = /404.html {
root /var/www/errors; # 错误页放在专用目录
internal; # internal 表示只允许内部跳转访问
}
location = /50x.html {
root /var/www/errors;
internal;
}
}
# 配合 return 指令快速返回自定义状态码
location /maintenance {
return 503; # 直接返回 503 状态码
}internal 指令的作用:禁止外部直接访问这个 location——只能由 error_page 内部跳转过来,防止用户直接访问 /404.html 看到 404 页面却返回 200。
7. 访问控制:限制 IP
有时候你想让后台管理界面只能内网访问,可以用 allow / deny:
# 访问控制(限制 IP)
server {
location /admin {
allow 192.168.1.0/24; # 允许内网
allow 10.0.0.0/8;
deny all; # 其他 IP 拒绝
}
location /api {
# 反向写法:只封禁某些 IP
deny 123.45.67.89;
allow all;
}
}规则是从上往下匹配,命中即停止。注意:如果用了反向代理,记得配合 set_real_ip_from 拿到真实客户端 IP(不然全是代理的 IP)。
8. 一个完整的虚拟主机配置模板
把上面的指令组合起来,下面是一个生产可用的静态站点模板,可以作为你写新站点的起点:
- 监听 80 端口;
- 匹配 example.com 和 www.example.com;
- 根目录 /var/www/example,首页 index.html;
- 自定义 404/50x 页面;
- 隐藏 Nginx 版本号;
- 记录访问日志到独立文件。
把这个模板存为 /etc/nginx/conf.d/example.com.conf,nginx -t && nginx -s reload 即可生效。建议把它作为你的团队标准模板,所有新项目都基于它复制修改。
小结
这一章你学会了用 server 块定义虚拟主机:通过 listen + server_name 区分多个站点,用 root/index/error_page 组织内容,用 allow/deny 做基础访问控制。下一篇我们深入 server 块内部的location 块——这是 Nginx 最强大也最容易绕晕的部分。
← 上一篇 nginx.conf 结构
下一篇 location 匹配规则 →