强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

虚拟主机配置

虚拟主机配置

虚拟主机(Virtual Hosts)允许一台 Apache 服务器托管多个网站,是共享主机和多站点部署的核心功能。

1. 虚拟主机类型

Apache 支持三种虚拟主机类型:

类型描述使用场景
基于域名不同域名指向同一 IP最常用,多站点托管
基于端口不同端口提供不同服务开发测试、内部服务
基于 IP不同 IP 地址SSL 传统配置(SNI 前)

2. 基于域名的虚拟主机

2.1 基本配置

# /etc/apache2/sites-available/example.conf

# 启用基于域名的虚拟主机
NameVirtualHost *:80  # Apache 2.2 需要,2.4 自动启用

<VirtualHost *:80>
    # 服务器名称
    ServerName www.example.com
    ServerAlias example.com www.example.net
    
    # 管理员邮箱
    ServerAdmin [email protected]
    
    # 文档根目录
    DocumentRoot /var/www/example.com/public_html
    
    # 日志配置
    ErrorLog /var/www/example.com/logs/error.log
    CustomLog /var/www/example.com/logs/access.log combined
    
    # 目录配置
    <Directory "/var/www/example.com/public_html">
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

2.2 多站点配置

# /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
    ServerName default.example.com
    DocumentRoot /var/www/default
    # 默认站点配置
</VirtualHost>

# /etc/apache2/sites-available/site1.conf
<VirtualHost *:80>
    ServerName site1.example.com
    DocumentRoot /var/www/site1
    ErrorLog /var/www/site1/logs/error.log
    CustomLog /var/www/site1/logs/access.log combined
    
    <Directory "/var/www/site1">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# /etc/apache2/sites-available/site2.conf
<VirtualHost *:80>
    ServerName site2.example.com
    DocumentRoot /var/www/site2
    ErrorLog /var/www/site2/logs/error.log
    CustomLog /var/www/site2/logs/access.log combined
    
    <Directory "/var/www/site2">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

2.3 泛域名配置

# 匹配所有子域名
<VirtualHost *:80>
    ServerName example.com
    ServerAlias *.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # 使用 mod_rewrite 处理子域名
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{HTTP_HOST} ^(.+)\.example\.com$ [NC]
        RewriteRule ^(.*)$ /subdomains/%1$1 [L]
    </IfModule>
    
    # 子域名目录结构
    # /var/www/example.com/public_html/subdomains/blog/
    # /var/www/example.com/public_html/subdomains/shop/
</VirtualHost>

2.4 启用站点

# Debian/Ubuntu 方式
sudo a2ensite site1.conf
sudo a2ensite site2.conf
sudo systemctl reload apache2

# 或手动创建符号链接
sudo ln -s /etc/apache2/sites-available/site1.conf /etc/apache2/sites-enabled/
sudo systemctl reload apache2

# 禁用站点
sudo a2dissite site1.conf
sudo systemctl reload apache2

3. 基于端口的虚拟主机

3.1 配置监听端口

# /etc/apache2/ports.conf
Listen 80
Listen 8080
Listen 8443

3.2 端口虚拟主机配置

# 主站点 - 端口 80
<VirtualHost *:80>
    ServerName www.example.com
    DocumentRoot /var/www/main
</VirtualHost>

# 管理后台 - 端口 8080
<VirtualHost *:8080>
    ServerName admin.example.com
    DocumentRoot /var/www/admin
    
    # 限制访问
    <Directory "/var/www/admin">
        Require ip 192.168.1.0/24
        Require ip 10.0.0.0/8
    </Directory>
</VirtualHost>

# API 服务 - 端口 8443
<VirtualHost *:8443>
    ServerName api.example.com
    DocumentRoot /var/www/api
    
    # SSL 配置
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/api.example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/api.example.com.key
</VirtualHost>

3.3 业务场景

开发环境:

# 开发服务器 - 不同端口对应不同项目
<VirtualHost *:80>
    ServerName project-a.dev
    DocumentRoot /home/dev/projects/a/public
</VirtualHost>

<VirtualHost *:8080>
    ServerName project-b.dev
    DocumentRoot /home/dev/projects/b/public
</VirtualHost>

<VirtualHost *:3000>
    ServerName project-c.dev
    DocumentRoot /home/dev/projects/c/public
</VirtualHost>

4. 基于 IP 的虚拟主机

4.1 配置多个 IP

# 添加多个 IP 地址
sudo ip addr add 192.168.1.101/24 dev eth0
sudo ip addr add 192.168.1.102/24 dev eth0

# 或配置网络接口
# /etc/network/interfaces
auto eth0:0
iface eth0:0 inet static
    address 192.168.1.101
    netmask 255.255.255.0

auto eth0:1
iface eth0:1 inet static
    address 192.168.1.102
    netmask 255.255.255.0

4.2 IP 虚拟主机配置

# 站点 A - IP 192.168.1.100
<VirtualHost 192.168.1.100:80>
    ServerName site-a.example.com
    DocumentRoot /var/www/site-a
</VirtualHost>

# 站点 B - IP 192.168.1.101
<VirtualHost 192.168.1.101:80>
    ServerName site-b.example.com
    DocumentRoot /var/www/site-b
</VirtualHost>

# 站点 C - IP 192.168.1.102
<VirtualHost 192.168.1.102:80>
    ServerName site-c.example.com
    DocumentRoot /var/www/site-c
</VirtualHost>

4.3 通配符 IP

# 监听所有 IP
<VirtualHost *:80>
    ServerName default.example.com
    DocumentRoot /var/www/default
</VirtualHost>

# 监听特定 IP
<VirtualHost 192.168.1.100:80>
    ServerName example.com
    DocumentRoot /var/www/example
</VirtualHost>

5. SSL 虚拟主机

5.1 基本 SSL 配置

# 启用 SSL 模块
# sudo a2enmod ssl

<VirtualHost *:443>
    ServerName www.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # SSL 配置
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/www.example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/www.example.com.key
    SSLCertificateChainFile /etc/ssl/certs/chain.pem
    
    # SSL 协议和密码套件
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder on
    
    # 日志
    ErrorLog /var/www/example.com/logs/ssl-error.log
    CustomLog /var/www/example.com/logs/ssl-access.log combined
</VirtualHost>

5.2 HTTP 到 HTTPS 重定向

# 方法 1:使用 mod_rewrite
<VirtualHost *:80>
    ServerName www.example.com
    RewriteEngine On
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

# 方法 2:使用 Redirect
<VirtualHost *:80>
    ServerName www.example.com
    Redirect permanent / https://www.example.com/
</VirtualHost>

# 方法 3:使用 mod_alias
<VirtualHost *:80>
    ServerName www.example.com
    RedirectMatch permanent ^/(.*)$ https://www.example.com/$1
</VirtualHost>

5.3 SNI(Server Name Indication)

SNI 允许在一个 IP 上托管多个 SSL 站点:

# 站点 A
<VirtualHost *:443>
    ServerName site-a.example.com
    DocumentRoot /var/www/site-a
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/site-a.crt
    SSLCertificateKeyFile /etc/ssl/private/site-a.key
</VirtualHost>

# 站点 B
<VirtualHost *:443>
    ServerName site-b.example.com
    DocumentRoot /var/www/site-b
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/site-b.crt
    SSLCertificateKeyFile /etc/ssl/private/site-b.key
</VirtualHost>

6. 虚拟主机配置最佳实践

6.1 配置模板

# /etc/apache2/sites-available/template.conf
<VirtualHost *:80>
    # 基本配置
    ServerName DOMAIN_NAME
    ServerAlias www.DOMAIN_NAME
    ServerAdmin admin@DOMAIN_NAME
    DocumentRoot /var/www/DOMAIN_NAME/public_html
    
    # 日志配置
    ErrorLog /var/www/DOMAIN_NAME/logs/error.log
    CustomLog /var/www/DOMAIN_NAME/logs/access.log combined
    
    # 目录配置
    <Directory "/var/www/DOMAIN_NAME/public_html">
        Options -Indexes +FollowSymLinks -MultiViews
        AllowOverride All
        Require all granted
    </Directory>
    
    # 安全头
    <IfModule mod_headers.c>
        Header always set X-Content-Type-Options "nosniff"
        Header always set X-Frame-Options "SAMEORIGIN"
        Header always set X-XSS-Protection "1; mode=block"
    </IfModule>
    
    # 禁止访问隐藏文件
    <FilesMatch "^\.">
        Require all denied
    </FilesMatch>
</VirtualHost>

6.2 脚本化配置

#!/bin/bash
# add-vhost.sh - 添加虚拟主机脚本

DOMAIN=$1
DOCROOT="/var/www/${DOMAIN}/public_html"
LOGDIR="/var/www/${DOMAIN}/logs"

# 创建目录
sudo mkdir -p ${DOCROOT} ${LOGDIR}

# 设置权限
sudo chown -R www-data:www-data /var/www/${DOMAIN}
sudo chmod -R 755 /var/www/${DOMAIN}

# 创建配置文件
sudo tee /etc/apache2/sites-available/${DOMAIN}.conf > /dev/null <<EOF
<VirtualHost *:80>
    ServerName ${DOMAIN}
    ServerAlias www.${DOMAIN}
    DocumentRoot ${DOCROOT}
    
    ErrorLog ${LOGDIR}/error.log
    CustomLog ${LOGDIR}/access.log combined
    
    <Directory "${DOCROOT}">
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
EOF

# 启用站点
sudo a2ensite ${DOMAIN}.conf
sudo systemctl reload apache2

echo "Virtual host ${DOMAIN} created successfully!"

6.3 验证虚拟主机配置

# 检查虚拟主机配置
apachectl -S

# 输出示例:
# VirtualHost configuration:
# *:80                   is a NameVirtualHost
#          default server default.example.com (/etc/apache2/sites-enabled/000-default.conf:1)
#          port 80 namevhost default.example.com (/etc/apache2/sites-enabled/000-default.conf:1)
#          port 80 namevhost site1.example.com (/etc/apache2/sites-enabled/site1.conf:1)
#                  alias www.site1.example.com
#          port 80 namevhost site2.example.com (/etc/apache2/sites-enabled/site2.conf:2)

# 测试配置语法
apachectl configtest

# 测试特定域名
curl -H "Host: site1.example.com" http://localhost/

7. 注意事项

  1. 配置顺序:Apache 按配置文件加载顺序处理虚拟主机,第一个匹配的配置生效
  2. 默认站点:建议配置一个默认虚拟主机作为兜底
  3. 日志分离:每个虚拟主机使用独立的日志文件
  4. 权限控制:确保 Apache 用户对所有文档根目录有读取权限
  5. DNS 配置:基于域名的虚拟主机需要正确的 DNS 解析
  6. 端口冲突:避免多个虚拟主机监听相同端口

8. 扩展阅读

9. 总结

虚拟主机是 Apache 最强大的功能之一:

  • 基于域名:最常用,支持 SNI 的 SSL
  • 基于端口:适合开发测试和内部服务
  • 基于 IP:传统方式,现在较少使用

合理规划虚拟主机结构可以提高服务器资源利用率,简化管理。