一、什么是虚拟主机
虚拟主机(Virtual Host)是 Apache 的核心功能之一,允许在一台物理服务器上托管多个网站。每个网站拥有独立的域名、文档根目录和配置,互不干扰。
Apache 支持三种虚拟主机方式:
| 类型 | 区分依据 | 适用场景 |
|---|---|---|
| 基于域名(Name-based) | HTTP 请求头中的Host字段 | 最常用,共享同一个 IP 地址 |
| 基于 IP(IP-based) | 不同的 IP 地址 | 需要独立 IP 的场景 |
| 基于端口(Port-based) | 不同的端口号 | 内部测试、特殊应用 |
本文重点介绍基于域名的虚拟主机,这是目前最主流、最实用的方案。
二、核心原理:基于域名的虚拟主机
2.1 工作原理
Apache 通过 HTTP 请求头中的Host字段来区分不同的网站。当浏览器访问http://set.charitize.dsz时,会在请求头中携带Host: set.charitize.dsz,Apache 根据这个字段匹配对应的<VirtualHost>块。
2.2 与单站点的核心区别
| 方面 | 初始配置(单站点) | 修改后配置(虚拟主机) |
|---|---|---|
| 站点数量 | 只有 1 个站点(全局DocumentRoot) | 多个虚拟主机(默认 + 隐藏子域名) |
| 匹配方式 | 所有请求都去同一个目录 | 根据Host请求头分发到不同目录 |
| 配置结构 | 全局DocumentRoot+Directory | 多个<VirtualHost>块 |
| 关键指令 | DocumentRoot "/var/www/localhost/htdocs" | NameVirtualHost *:80+<VirtualHost *:80> |
三、配置步骤详解
3.1 启用虚拟主机功能
在 Apache 2.2 中,需要显式启用NameVirtualHost指令:
NameVirtualHost *:80作用:告诉 Apache 启用基于域名的虚拟主机功能,监听所有 IP 的 80 端口。如果没有这个指令,Apache 会将所有请求交给第一个VirtualHost处理。
在 Apache 2.4 中,
NameVirtualHost已被废弃,默认自动启用基于域名的虚拟主机。
3.2 配置默认虚拟主机
当使用虚拟主机时,全局的DocumentRoot会被忽略,必须将站点配置放在VirtualHost块中。
<VirtualHost *:80> ServerName localhost ServerAlias default DocumentRoot "/var/www/localhost/htdocs" <Directory "/var/www/localhost/htdocs"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/localhost_error.log CustomLog ${APACHE_LOG_DIR}/localhost_access.log combined </VirtualHost>作用:
- 处理访问
localhost的请求 - 作为默认站点,处理所有未匹配到的域名请求(包括直接 IP 访问、未知域名)
3.3 配置隐藏子域名虚拟主机
<VirtualHost *:80> ServerName set.charitize.dsz DocumentRoot "/var/www/set" <Directory "/var/www/set"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/set_error.log CustomLog ${APACHE_LOG_DIR}/set_access.log combined </VirtualHost>作用:只处理Host: set.charitize.dsz的请求,访问其他域名不会看到这个站点。
3.4 完整配置示例
# 启用基于域名的虚拟主机(Apache 2.2 需要) NameVirtualHost *:80 # 默认虚拟主机(必须放在第一位,作为 fallback) <VirtualHost *:80> ServerName localhost ServerAlias default DocumentRoot "/var/www/localhost/htdocs" <Directory "/var/www/localhost/htdocs"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/localhost_error.log CustomLog ${APACHE_LOG_DIR}/localhost_access.log combined </VirtualHost> # 隐藏子域名虚拟主机 <VirtualHost *:80> ServerName set.charitize.dsz DocumentRoot "/var/www/set" <Directory "/var/www/set"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/set_error.log CustomLog ${APACHE_LOG_DIR}/set_access.log combined </VirtualHost>四、请求处理流程
匹配规则:
- Apache 收到请求后,读取 HTTP 头中的
Host字段 - 精确匹配
ServerName→ 返回对应站点内容 - 未精确匹配 → 走第一个
VirtualHost(默认站点)
五、常见问题与解决
5.1 为什么配置了 VirtualHost 后原来的站点无法访问?
原因:配置VirtualHost后,Apache 进入"虚拟主机模式"。在这个模式下:
- 全局的
DocumentRoot被忽略 - 只有
VirtualHost块中定义的站点才能被访问 - 如果没有定义处理原来域名(如
localhost或直接 IP 访问)的VirtualHost,原来的内容就无法访问
解决:添加一个默认VirtualHost,将原来的配置移入其中。
5.2 如何验证虚拟主机配置?
# 列出所有虚拟主机sudoapachectl-S输出示例:
VirtualHost configuration: *:80 localhost (/etc/apache2/httpd.conf:162) *:80 set.charitize.dsz (/etc/apache2/httpd.conf:175)5.3 如何添加更多站点?
只需增加新的<VirtualHost *:80>块,指定不同的ServerName和DocumentRoot:
<VirtualHost *:80> ServerName blog.example.com DocumentRoot "/var/www/blog" ... </VirtualHost>5.4 403 Forbidden 错误?
可能原因:
- 目录权限不正确:
sudo chmod -R 755 /var/www - 配置中缺少
Require all granted - SELinux 未关闭(CentOS):
sudo setenforce 0
六、关键指令速查表
| 指令 | 作用 |
|---|---|
NameVirtualHost *:80 | 启用基于域名的虚拟主机(Apache 2.2) |
<VirtualHost *:80> | 定义一个虚拟主机块 |
ServerName | 设置虚拟主机的主域名 |
ServerAlias | 设置虚拟主机的别名域名 |
DocumentRoot | 设置站点的文档根目录 |
ErrorLog | 设置错误日志路径 |
CustomLog | 设置访问日志路径 |
七、总结
| 问题 | 答案 |
|---|---|
| 为什么要加默认虚拟主机? | 让原来直接访问 IP/localhost 的用户还能看到原来的网站 |
| 为什么隐藏子域名生效? | Apache 根据Host请求头精确匹配ServerName |
| 访问顺序是什么? | 精确匹配ServerName→ 匹配不到的走第一个VirtualHost(默认站点) |
| 如何添加更多隐藏站点? | 增加新的<VirtualHost *:80>块,指定不同的ServerName和DocumentRoot |
虚拟主机是 Apache 最实用的功能之一,通过基于域名的方式,可以在一台服务器上高效托管多个独立站点,既节省资源又便于管理。