背景

一台机器上往往不止一个站:静态博客占一个端口,别的应用占 80。
「绑定域名」在 Nginx 里并不是改 hosts 就完事,核心是 server 块 + server_name + Host 头匹配,再配上是否做 default_server、是否反向代理。

本文依据 Nginx 官方文档整理,配置一律用示例域名,不涉及真实环境信息。


1. 请求如何选中一个 server

官方 How nginx processes a request 的顺序可以概括为:

  1. 连接先落在某个 listen 端口 的默认 server 上下文
  2. 解析请求行
  3. 解析 Host 头
  4. 用 Host 值在该端口的 server 里找 server_name
  5. 找不到 → 落到该端口的 default server

要点:

default_server 是 listen 端口的属性,不是 server_name 的属性。

server {
    listen 80 default_server;
    server_name _;
    # 兜底应用(示例:旧系统)
}

server {
    listen 80;
    server_name blog.example.org;
    # 博客
}

Host: blog.example.org → 第二个块;
Host: 1.2.3.4 或乱填域名 → 第一个块(default)。


2. server_name 怎么写

官方 Server names 支持:

写法含义例子
精确名完全匹配blog.example.org
前缀通配仅允许 *. 开头*.example.org
后缀通配仅允许 .* 结尾mail.*
正则~ 开头~^(?<sub>.+)\.example\.org$
.example.org裸域 + 任意子域匹配 example.org 与 www.example.org
_非法域名当哨兵常用于 catch-all

匹配优先级(命中即停):

  1. 精确名
  2. 最长的 *.… 通配
  3. 最长的 …* 通配
  4. 配置文件中第一个匹配的正则

实践建议: 能写精确名就写精确名;正则最慢,名字多时别滥用。

完整示例:

server {
    listen 80;
    server_name blog.example.org www.blog.example.org;
    root /var/www/blog;
    index index.html;
}

3. 绑定域名的最小可用步骤

按依赖顺序,缺一不可:

DNS A/AAAA 记录 → 服务器公网 IP
       ↓
云安全组放行 80(及需要的 443/自定义端口)
       ↓
Nginx server { listen ...; server_name 你的域名; }
       ↓
nginx -t && systemctl reload nginx
       ↓
curl -H "Host: 你的域名" http://127.0.0.1/   # 本机先验
       ↓
浏览器访问 http://你的域名/

DNS 没生效、安全组没放行、server_name 拼错,都会表现成「绑了域名却打不开」。


4. 静态站:直接绑域名

server {
    listen 80;
    server_name blog.example.org;

    root /home/deploy/projects/my-blog/current;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
  • root 指向构建产物目录(例如静态站的 dist)
  • try_files:找不到文件再回退目录索引,避免错误 404 行为混乱
  • 改配置后务必 nginx -t,再 reload

5. 反向代理绑域名(同机多服务很常见)

当 80 已被占用,或需要「域名走 A、IP/另一域名走 B」时:

# 按 Host 分流:域名 → 本机另一端口的博客
server {
    listen 80;
    server_name blog.example.org;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        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;
    }
}

# 其它流量 → 默认应用
server {
    listen 80 default_server;
    server_name _;
    # 原有应用或静态页
}

为什么必须传 Host

官方 Reverse Proxy 说明:默认会改写 Host(变成 $proxy_host)。
若后端也靠虚拟主机选站,不传 proxy_set_header Host $host 会串站。

proxy_set_header Host $host;

6. 同端口多站点:加载顺序坑

配置放在 conf.d/*.conf 时,文件名会影响加载顺序;
未显式写 default_server 时,该 listen 上第一个 server 块成为默认站。

常见事故:

  1. 新加的 agents.example.conf 字母序排在 default.conf 前面
  2. 默认站被抢走
  3. 用 IP 访问时进了新站,原应用「突然打不开」

规避:

# 原主站显式钉死
listen 80 default_server;

# 新域名站不要写 default_server
listen 80;
server_name blog.example.org;

改完用两种 Host 各测一次:

curl -sI -H 'Host: blog.example.org' http://127.0.0.1/ | head
curl -sI -H 'Host: 192.0.2.10'      http://127.0.0.1/ | head

(192.0.2.10 为文档示例地址,按你的机器替换。)


7. 常见故障排查表

现象优先检查
域名打不开,IP 正常DNS 是否指向正确、server_name 是否完全一致(含不带 www)
打开是另一个站Host 匹配到了 default 或另一个 server;查 server_name 与 conf 加载顺序
403root 路径权限、目录是否可读、是否有 index 文件
404 但文件存在root/alias 是否多写了一层路径
反代后后端认错站是否缺少 proxy_set_header Host $host
reload 无效是否改了错误环境的配置;是否只 nginx -t 未 reload
端口起不来是否被其它进程占用、是否误监听已占用端口

快速自检命令:

nginx -t
systemctl is-active nginx
ss -lptn | grep nginx
curl -v -H 'Host: blog.example.org' http://127.0.0.1/

8. 什么时候用精确名、通配、正则

场景推荐
一域名一站精确名
一批子域同一套静态*.example.org
仅裸域 + www写两个精确名,或 .example.org
动态按子域选目录正则 + 命名捕获(谨慎,注意性能)

官方优化说明:精确名进 hash,正则线性扫描;域名很多时优先精确/通配。


9. 和「多层 Nginx」的关系

很多环境是:

浏览器
  → 边缘/容器 Nginx(:80/:443,按域名分流)
      → 系统 Nginx 或应用端口(:8080 等)

绑域名时要分清 哪一层 在做 server_name:

  • 边缘层负责「域名 → 哪条上游」
  • 内层可继续 server_name 或只当静态/反代

两层都写 server_name 时,边缘必须已经把正确 Host 传下去(proxy_set_header Host $host)。


10. 结论

Nginx 绑定域名可以收成四句:

  1. DNS + 安全组 先通,再谈配置
  2. server_name 对齐 Host,写不清就进 default
  3. default_server 显式声明,避免加载顺序抢默认站
  4. 反代必传 Host $host,否则后端再绑域名会串站

配置改完固定动作:nginx -t → reload → 带 Host 的 curl 验证 → 浏览器复测。


参考

  1. Nginx. Server names. https://nginx.org/en/docs/http/server_names.html
  2. Nginx. How nginx processes a request. https://nginx.org/en/docs/http/request_processing.html
  3. Nginx/F5. NGINX Reverse Proxy. https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/