多个域名共用同一documentroot时,应使用一个virtualhost块配合servername和serveralias,而非多个virtualhost块;servername设主域名,serveralias列其余域名,hosts文件需逐条映射,避免配置冗余导致匹配失效。

多个域名共用同一 DocumentRoot,别写多个 <virtualhost></virtualhost> 块
直接在一个 <virtualhost></virtualhost> 块里用 ServerName + ServerAlias,是最简、最稳的做法。写多个块看似“清晰”,实则触发 Apache 的匹配 fallback 机制:只有第一个块生效,其余域名全被路由到它——你改第二个块的 DocumentRoot,两个域名内容一起变;加第三个块后 httpd -t 报错 DocumentRoot must be a directory,往往就是路径不存在或权限不对,但根因是冗余配置干扰了加载顺序。
正确写法示例:
<virtualhost>
ServerName dev.local
ServerAlias site1.local site2.local test.dev
DocumentRoot "/var/www/myapp"
<directory>
Require all granted
</directory></virtualhost>
-
ServerName必须且只能写一个,且要和/etc/hosts(或C:\Windows\System32\drivers\etc\hosts)中映射的主域名完全一致 -
ServerAlias后跟所有其他域名,空格分隔,不支持通配符映射到 hosts 文件(*.dev.local在 Apache 配置里合法,但 hosts 文件必须逐条写127.0.0.1 site1.local、127.0.0.1 site2.local) -
DocumentRoot路径结尾不加斜杠;目录需真实存在、Apache 进程有读取权限(Linux 下常用chown -R $APACHE_RUN_USER:$APACHE_RUN_GROUP /var/www/myapp)
多个域名指向不同网站目录,每个 <virtualhost></virtualhost> 块必须独立
当你要托管 site-a.com 和 site-b.com 两个完全不同的站点时,必须用两个分离的 <virtualhost></virtualhost> 块,各自定义 ServerName、DocumentRoot 和 <directory></directory> 权限。这不是“风格选择”,而是 Apache 匹配逻辑决定的:它靠 Host 请求头精确匹配 ServerName 或 ServerAlias,不匹配就 fallback 到第一个块(或默认主机)。
常见错误现象:
- 访问
site-b.com显示的是site-a.com的首页 → 第二个块没生效,可能ServerName拼错(如写成www.site-b.com但浏览器输的是site-b.com),或未启用mod_vhost_alias - 两个域名都报 403 Forbidden →
<directory></directory>权限块缺失或Require规则写错(Apache 2.4+ 不再认Order allow,deny) - 日志里反复出现
client denied by server configuration→ 检查<directory></directory>是否覆盖了实际路径,比如写成<directory></directory>却把文件放到了/var/www/site-a/public
HTTPS 多域名必须启用 SNI,且每个 <virtualhost></virtualhost> 独占证书
单 IP 绑定多个 HTTPS 域名,靠的是 SNI(Server Name Indication)。它要求客户端在 TLS 握手初期明文发送域名,Apache 才能加载对应证书。但这个机制脆弱:任意一环断掉,所有域名都会返回第一个块的证书(浏览器提示“证书与域名不匹配”)。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
关键检查点:
- 运行
httpd -V | grep -i ssl,确认输出含 OpenSSL 版本(≥ 0.9.8f),且mod_ssl已加载(a2enmod ssl或检查httpd.conf中LoadModule ssl_module modules/mod_ssl.so未注释) - 每个
<virtualhost></virtualhost>块内必须完整定义:SSLEngine on、SSLCertificateFile、SSLCertificateKeyFile,禁止在全局配置里设证书路径 -
ServerName必须和证书 SAN(Subject Alternative Name)字段完全一致(site-a.com≠www.site-a.com,除非证书里同时包含两者) - Let’s Encrypt 用户务必对每个域名单独运行
certbot --apache -d site-a.com -d www.site-a.com,不要跨域名复用同一组证书文件
httpd -t 验证后一定要重启 Apache,别跳过这步
配置改完,httpd -t(Linux/macOS)或 httpd -t(Windows)通过只代表语法无误,不代表 Apache 已加载新配置。尤其是当你修改的是 conf/extra/httpd-vhosts.conf 这类被 Include 的子配置时,很容易忘记检查主配置里 Include conf/extra/httpd-vhosts.conf 是否已取消注释。
典型遗漏点:
- Debian/Ubuntu 系统下,
sites-available里的文件没用a2ensite启用,或启用后没systemctl reload apache2 - CentOS/RHEL 中,
httpd.conf里IncludeOptional conf.d/*.conf没覆盖你的配置文件名(比如你叫my-vhosts.conf,但conf.d/下只有*.conf) - Windows 上改了
httpd-vhosts.conf,但httpd.conf里这行仍是注释状态:# Include conf/extra/httpd-vhosts.conf - 改完 hosts 文件后没清浏览器 DNS 缓存(Chrome 地址栏输
chrome://net-internals/#dns清空),导致始终解析不到本地
真正生效的信号只有一个:重启服务后,curl -I http://site1.local 和 curl -I https://site2.com 都返回 200,且 DocumentRoot 内容正确。任何中间环节省略,都可能让配置“看起来对,其实没跑”。









