在一台服务器上同时运行多个网站时,最怕遇到的情况是:域名都指向了同一个 IP,访问结果却始终是同一个默认页面。要解决这个问题,就需要理解 Nginx 的虚拟主机机制。Nginx 并不是为每个站点启动一个独立进程,而是在配置文件中用 server 块来定义不同的站点规则。请求进来后,Nginx 会先读取 HTTP 头部的 Host 字段,再与各个 server_name 做匹配,匹配成功后才把请求交给对应的站点目录处理。

一、先弄清 Nginx 虚拟主机与配置文件结构
Nginx 的主配置文件通常位于 Linux 系统的 /etc/nginx/nginx.conf,Windows 解压版则位于 C:\nginx\conf\nginx.conf。这个文件主要负责全局参数设置,而具体的站点配置通常会通过 include 指令引入到 http 块中。常见的引入目录有 /etc/nginx/conf.d/*.conf 和 /etc/nginx/sites-enabled/* 两种。你可以先打开主配置文件,确认里面到底引入了哪个目录,避免把自己新建的站点配置文件放错位置。
下面这段配置展示了一个典型的 http 块结构。可以看到虚拟主机配置文件并不是直接写在主文件里,而是统一放进独立目录,这样每新增一个站点只需要新建一个 .conf 文件,不会影响其他站点。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 引入虚拟主机配置目录
include /etc/nginx/conf.d/*.conf;
}
每个虚拟主机由一个 server 块组成。一个 server 块内部最少需要包含以下几个核心指令:listen 表示监听端口,server_name 表示域名或主机名,root 表示站点文件目录,index 表示默认首页文件。理解了这些指令后,配置虚拟主机就是按顺序填写规则,再用重载命令让配置生效。
二、基于域名的虚拟主机配置步骤
基于域名的虚拟主机是最常用的方式。假设你有一台服务器,两个域名都解析到同一个 IP,但希望访问 ipipp.com 时打开 A 站点,访问 test.com 时打开 B 站点。第一步是创建两个站点的根目录,并放入测试页面。Linux 下可以使用下面的命令快速创建目录和首页文件。
sudo mkdir -p /var/www/ipipp.com/html echo "<h1>Hello from ipipp.com</h1>" | sudo tee /var/www/ipipp.com/html/index.html sudo mkdir -p /var/www/test.com/html echo "<h1>Hello from test.com</h1>" | sudo tee /var/www/test.com/html/index.html
Windows 用户可以手动创建 C:\www\ipipp.com 和 C:\www\test.com 两个目录,并在里面分别放入一个 index.html 文件。目录路径可以根据习惯调整,但后续配置中的 root 必须与之一致。
第二步是创建站点配置文件。在确认主配置引入的是 conf.d 目录后,新建 /etc/nginx/conf.d/ipipp.com.conf 文件,写入以下内容。这个配置表示监听 80 端口,当请求的 Host 为 ipipp.com 或 www.ipipp.com 时,使用 /var/www/ipipp.com/html 作为站点目录。
server {
listen 80;
server_name ipipp.com www.ipipp.com;
root /var/www/ipipp.com/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
try_files 指令会让 Nginx 先尝试查找请求对应的文件,再尝试目录,最后找不到时返回 404。这样可以避免一些简单的路径泄露问题。第二个域名 test.com 的配置方式完全相同,只需要把 server_name 和 root 换成对应值即可。
第三步是测试并重载配置。每次修改配置文件后,都应该先执行 nginx -t 检查语法。如果输出 syntax is ok 和 test is successful,说明没有语法问题,再执行 sudo systemctl reload nginx 或 sudo nginx -s reload 让配置生效。Windows 下可以直接在 Nginx 安装目录执行 nginx -t 和 nginx -s reload。本地测试时如果还没有真实域名,可以修改 hosts 文件,Windows 路径为 C:\Windows\System32\drivers\etc\hosts,Linux 路径为 /etc/hosts,将 127.0.0.1 映射到 ipipp.com 和 test.com。
三、基于端口或 IP 的虚拟主机配置
如果你的服务器只有一个域名,或者不想为了测试修改 hosts 文件,也可以让不同站点监听不同端口。Nginx 会优先根据 listen 指令中的 IP 和端口组合来区分请求。例如下面的配置让 8080 端口对应 A 站点,9090 端口对应 B 站点。这里 server_name _ 表示不限制域名,任何 Host 都可以匹配。
server {
listen 8080;
server_name _;
root /var/www/site-a;
index index.html;
}
server {
listen 9090;
server_name _;
root /var/www/site-b;
index index.html;
}
基于端口的虚拟主机很适合本地同时开发多个前端项目,通过 localhost:8080、localhost:9090 就能分别访问不同目录,不需要频繁修改域名解析。而基于 IP 的虚拟主机则要求服务器绑定多个 IP 地址,每个 server 块的 listen 直接写对应 IP,例如 listen 192.0.2.10:80;。这种方式在实际生产中已经比较少用,因为域名加端口的方式更灵活,也更容易维护。
| 虚拟主机类型 | 区分依据 | 典型场景 |
|---|---|---|
| 基于域名 | 请求头中的 Host | 一台服务器部署多个网站 |
| 基于端口 | 监听端口号 | 本地开发或临时测试 |
| 基于 IP | 目标 IP 地址 | 特殊网络环境或多 IP 主机 |
四、新手高频问题与注意事项
第一个高频问题是域名配置后访问仍然显示默认欢迎页。这通常不是因为配置没写对,而是浏览器缓存、DNS 未更新或请求 HOST 不匹配。排查时可以先在服务器本地执行 curl -H "Host: ipipp.com" http://127.0.0.1/,如果返回的是目标页面而不是欢迎页,说明 Nginx 配置已经生效,问题出在 DNS 或浏览器。另一个常见原因是没有配置 default_server,当请求的域名没有匹配到任何 server_name 时,Nginx 会使用第一个 server 块处理。可以在主配置里增加一个默认拒绝站点,避免未绑定域名直接访问到你的业务站点。
server {
listen 80 default_server;
server_name _;
return 444;
}
第二个高频问题是静态资源返回 403 或 404。404 通常意味着 root 路径写错,或者 location 块的规则把所有请求都拦截了。403 则多数是文件权限问题。Linux 下 Nginx 多以 nginx 或 www-data 用户运行,该用户需要对站点目录拥有读取权限,目录一般设置为 755,文件设置为 644 即可。如果权限看起来正常但仍然被拒,还需要检查 SELinux 或 AppArmor 是否拦截了访问。
第三个问题是修改配置后重载失败。这时候不要直接重启服务,先执行 nginx -t,它会明确告诉你哪一行有语法错误。常见错误包括少写分号、括号不闭合、指令拼写错误等。修复后再执行重载。另一个容易忽略的点是,多个 server 块如果出现相同的 server_name 并不会报错,但请求只会匹配到最先出现的那个块。因此配置多个站点时要保证域名不重复,或者有意使用默认站点来处理无效域名请求。
最后还要注意,Nginx 配置修改后必须重载才能生效,仅保存文件不会自动加载。重载命令比完全重启更平滑,一般不会中断现有连接。养成每次修改后先 nginx -t 再重载的习惯,可以避免大部分因配置错误导致的服务不可用问题。掌握了这些步骤和排查思路,配置 Nginx 虚拟主机就不是什么难事了。