nginx中多个server_name在同一server块内仅第一个生效,因sni证书匹配仅依赖首个域名;多域名需分设独立server块并配置对应ssl证书。

nginx 多个 server_name 为什么只生效一个
因为 server_name 只在有多个 server 块共存时才起路由作用。如果配置文件里只有一个 server,哪怕你写了 server_name example.com,所有发到该 IP+端口的请求都会命中它——Nginx 根本不校验域名。
常见错误现象:
- 改了
server_name却发现访问任意域名都显示同一个网站 - 用
curl -H "Host: test.example.com" http://your-ip测试时能走对配置,但浏览器直接输域名却不行 → DNS 或本地/etc/hosts没配对
实操建议:
- 每个域名必须对应一个独立的
server块(不能塞进同一个块里用多个server_name分割) - 确保所有
server块的listen指令一致(比如都是listen 80),否则可能被系统级端口监听优先级干扰 - 泛域名写法是
server_name *.example.com;,但注意它不匹配根域名example.com,要单独加一个server_name example.com;块
Apache 的 VirtualHost 配置后访问 403 Forbidden
这不是权限问题,大概率是 DocumentRoot 对应目录没开读取权限,或 Apache 没被允许进入该路径。
关键点:
-
DocumentRoot /var/www/site_a要求 Apache 进程(通常是www-data或apache用户)对整个路径有执行(x)权限,否则进不去目录 - 目录本身和父级目录都要有
chmod +x,尤其/var/www默认可能只有root可执行 -
<directory></directory>块里必须有Require all granted(Apache 2.4+);旧版用Order allow,deny+Allow from all
检查顺序建议:
- 运行
sudo apache2ctl -t确认语法无误 - 查日志:
tail -f /var/log/apache2/error.log,看到类似client denied by server configuration就是上面的权限或Require配置漏了 - 别忘了启用站点:
a2ensite site_a.conf,否则配置文件只是躺在sites-available里没加载
如何让 nginx 同时支持 www 和非 www 域名跳转
不要靠 DNS 解析或客户端重定向,用 Nginx 原生 return 301 最干净,也避免 HTTPS 混合内容问题。
典型写法(以强制跳转到 www 为例):
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# 正常配置
}
注意事项:
-
$request_uri必须带上,否则带参数或路径的请求会丢失 - HTTPS 场景下,
return 301 https://...是安全的;如果用http://会被现代浏览器拦截(Mixed Content) - 别在同一个
server块里又写server_name example.com www.example.com又想跳转——它俩会平级匹配,跳转逻辑不会触发
配置完 reload 不生效?先跑这三步
不是 reload 失败,而是你没确认到底 reload 了哪个配置、有没有语法错误、进程是否真重启了。
必做检查项:
- nginx:运行
sudo nginx -t,输出必须是test is successful;失败时它不会 reload,但很多人没看输出就直接systemctl reload nginx - Apache:运行
sudo apache2ctl -t,同样要成功;且确认systemctl status apache2显示的是 active (running),不是 failed - 检查实际生效的配置路径:
nginx -V 2>&1 | grep conf或apache2ctl -V | grep SERVER_CONFIG_FILE,避免改错文件(比如改了/etc/nginx/sites-available却没软链到sites-enabled)
最易忽略的一点:修改了 /etc/hosts 或 DNS 解析,但浏览器缓存了旧的 IP,或者用了代理/CDN 缓存了 301 跳转。测试前清空浏览器 DNS 缓存,或用 curl -v http://your-domain 直接看响应头和真实 IP。











