在一台服务器上同时托管多个网站时,如果为每个域名单独分配一台物理机或虚拟机,不仅资源利用率低,维护成本也会明显上升。Apache 提供的虚拟主机机制正是为了应对这种需求:它允许一个 Apache 实例根据请求中的域名、目标 IP 或端口,将流量分发到不同的站点目录。换句话说,多个站点可以共享同一份 Apache 主程序,却表现出彼此独立、互不干扰的效果。实际部署里最常用的是基于域名的虚拟主机配置,也就是常说的 Name-based Virtual Host。本文从工作方式讲起,再给出可落地的配置步骤、扩展用法和排查方法。

一、Apache虚拟主机的工作方式与前置条件
Apache 的虚拟主机可以按三种维度划分:基于域名、基于 IP、基于端口。基于域名时,服务器只监听一个 80 端口,但根据 HTTP 请求头中的 Host 字段判断用户想访问哪个站点。Host 头由浏览器自动携带,例如访问 www.ipipp.com 时,请求头中会包含 Host: www.ipipp.com。Apache 拿这个值和每个 <VirtualHost> 中的 ServerName、ServerAlias 比对,找到匹配项后,再把请求交给对应的 DocumentRoot。
配置基于域名的虚拟主机前,需要先满足几个条件。第一,域名必须能解析到服务器 IP。生产环境在 DNS 控制台添加 A 记录;本地测试可以在 hosts 文件里写入映射,Linux 路径是 /etc/hosts,Windows 路径是 C:\Windows\System32\drivers\etc\hosts。第二,Apache 的运行用户必须对站点目录有读取权限,否则请求会被拒绝。第三,确认 Apache 版本:2.4 之后的版本已经内置对基于域名虚拟主机的支持,不需要再写 NameVirtualHost 指令;如果是老旧 2.2 版本,则需要额外指定 NameVirtualHost *:80。
还要理解默认虚拟主机这个概念。当请求中的 Host 与所有 ServerName、ServerAlias 都不匹配时,Apache 会使用配置文件中第一个出现的虚拟主机来响应。这个行为在线上环境尤其重要:如果服务器 IP 被无关域名解析过来,默认站点就会承接这些请求。因此,建议把最不希望暴露的站点或一个专门的默认页面放在配置顺序第一位。
二、基于域名的VirtualHost配置详细步骤
先创建站点目录和测试页面。以 Debian/Ubuntu 常见的 /var/www 为例,给 ipipp.com 创建独立目录,并放入一个简单 index.html。目录名可以按项目命名,关键是路径要与后面的 DocumentRoot 完全一致。执行以下命令完成创建和权限调整:
sudo mkdir -p /var/www/example/public_html echo '站点测试页面' > /var/www/example/public_html/index.html sudo chown -R www-data:www-data /var/www/example/public_html
接着创建虚拟主机配置文件。Debian/Ubuntu 通常把文件放在 /etc/apache2/sites-available/ 下,再通过 a2ensite 启用;CentOS/RHEL 则可以直接放到 /etc/httpd/conf.d/ 下,只要文件名以 .conf 结尾就会被自动加载。下面是一个最小可用的基于域名配置:
<VirtualHost *:80>
ServerName www.ipipp.com
ServerAlias ipipp.com
DocumentRoot "/var/www/example/public_html"
<Directory "/var/www/example/public_html">
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog "/var/log/apache2/example-error.log"
CustomLog "/var/log/apache2/example-access.log" combined
</VirtualHost>
这里 <VirtualHost *:80> 表示匹配所有 IP 的 80 端口;ServerName 是主域名;ServerAlias 是可选别名;DocumentRoot 指向站点根目录;<Directory> 块控制该目录的访问策略;ErrorLog 和 CustomLog 分别记录错误和访问日志。其中 Require all granted 是 Apache 2.4 的授权写法,不能遗漏,否则可能出现 403。
启用站点并让配置生效。Debian/Ubuntu 使用 sudo a2ensite ipipp.com.conf 创建 sites-enabled 下的软链接,再执行 sudo systemctl reload apache2;CentOS/RHEL 因为 conf.d 自动加载,直接 sudo systemctl reload httpd 即可。每次修改配置后都应先运行 apachectl configtest 检查语法,确认返回 Syntax OK 后再 reload。reload 比 restart 更平滑,不会中断现有连接。
本地没有真实 DNS 时,可以先修改 hosts 文件,将 127.0.0.1 指向 www.ipipp.com,然后浏览器访问 http://www.ipipp.com。也可以用 curl 指定 Host 头来验证,例如 curl -H "Host: www.ipipp.com" http://127.0.0.1/。看到测试页面说明虚拟主机已经命中;如果看到默认站点,则说明 Host 匹配失败。
三、ServerAlias、日志隔离与默认站点兜底
ServerAlias 用于让多个域名共享同一个站点。比如用户同时注册了 ipipp.com 和 example.net,希望两者打开相同内容,不必复制两份配置,只需在 ServerAlias 后追加域名即可。多个域名用空格分隔,也支持通配符,例如 *.ipipp.com 可以匹配 blog.ipipp.com、shop.ipipp.com 等所有子域。不过通配符只匹配一层,不能跨多级子域。
日志隔离是虚拟主机配置中容易被忽略但很有价值的细节。如果所有站点都写入同一个 access.log,流量上来后很难区分哪个域名产生了哪些请求。给每个虚拟主机单独指定 ErrorLog 和 CustomLog 后,排查问题会直观很多。CustomLog 后面的 combined 表示使用 Apache 内置的组合日志格式,包含客户端 IP、时间、请求行、状态码、Referer 和 User-Agent。
默认站点兜底建议单独配置。可以把一个只返回提示信息的静态页作为第一个虚拟主机,ServerName 设置为服务器 IP 或 _default_。这样当有人通过未配置域名访问服务器时,不会看到任意一个正式站点,既避免内容泄露,也方便识别异常解析。对于 2.4 版本,顺序就是第一个 <VirtualHost>;也可以使用 _default_ 作为地址来明确表示默认。
四、基于IP和端口的虚拟主机、HTTPS与排查方法
除了基于域名,Apache 还支持基于 IP 和基于端口的虚拟主机。基于 IP 的配置需要服务器绑定多个 IP,每个 <VirtualHost> 的地址部分写具体 IP。基于端口则需要先在主配置中增加 Listen 8080 等端口,再创建对应容器。这两种方式适合某些老式客户端不支持 Host 头,或需要按端口隔离服务的情况。
Listen 8080
<VirtualHost *:80>
ServerName www.ipipp.com
DocumentRoot "/var/www/example/public_html"
</VirtualHost>
<VirtualHost *:8080>
ServerName admin.ipipp.com
DocumentRoot "/var/www/admin/public_html"
</VirtualHost>
生产环境启用 HTTPS 时,虚拟主机会变得更复杂一些。需要加载 mod_ssl 模块,并创建 443 端口容器。证书路径要指向真实有效的文件,配置修改后依然要执行 configtest 和 reload。HTTPS 虚拟主机同样支持 ServerName 和 ServerAlias,但同一 IP 的 443 端口通常只能承载一个证书,若要多域名不同证书,需要 SNI 或使用多 IP。
<VirtualHost *:443>
ServerName www.ipipp.com
DocumentRoot "/var/www/example/public_html"
SSLEngine on
SSLCertificateFile "/etc/ssl/example.crt"
SSLCertificateKeyFile "/etc/ssl/private/example.key"
SSLCertificateChainFile "/etc/ssl/chain.crt"
</VirtualHost>
遇到配置不生效时,可以按顺序排查。先运行 apachectl configtest 看是否有语法错误;再用 apachectl -S 列出已加载的虚拟主机和默认主机,确认顺序是否符合预期。403 错误大概率是目录权限不足或缺少 Require all granted;404 则要检查 DocumentRoot 路径和文件名大小写。DNS 未生效时先看 hosts 文件,再抓包或看 access log 中实际到达的 Host 头。端口冲突常见于 80 或 443 被其他程序占用,用 netstat -tlnp 可以快速确认。
虚拟主机是 Apache 运维的基础能力,基于域名配置足以应对多数单机多站场景。掌握目录准备、配置文件编写、语法检查和 reload 流程,再配合 ServerAlias、日志隔离和默认站点兜底,基本能搭建出稳定易维护的多站点环境。后续遇到更复杂的网络架构,再逐步引入基于 IP、端口和 HTTPS 的配置即可。
Apache虚拟主机VirtualHost配置Apache配置修改时间:2026-10-03 05:00:22