我也遇到了关于apache2动态虚拟主机回退的问题,Luc的回答对解决我的问题有很大帮助,但是我仍然想展示我为实现目标所做的工作,主要是因为它涉及一些额外的工作,而且我认为对将来的任何Google员工可能会有帮助...
我的目标
- 指向我的VPS的所有域和子域的动态虚拟主机
foo.com
应该与 www.foo.com
- 将未知域回退到某种默认值
- 回退为未知的子域
foo.com
来www.foo.com
,除非www
是不可用的,退回到默认,而不是
域名解析
我有几个指向VPS的域(及其所有子域),例如:
- foo.com
- bar.com
- foobar.com
文件系统
我有以下目录,域包含具有可用子域名称的目录,www目录是必需的,但配置应该能够处理不存在该目录的情况。Localhost用作默认回退:
/var
/www
/localhost
/foo.com
/www
/bar
/bar.com
/foo
测验
将我的目标转化为可测试的案例:
- foo.com应该从foo.com/www提供
- www.foo.com应该从foo.com/www提供
- 应该从foo.com/bar提供bar.foo.com
- foo.foo.com应该通过foo.com/www提供(foo.com/foo不存在)
- bar.com应该从服务本地主机(bar.com/www不存在)
- www.bar.com应该从本地主机提供(bar.com/www不存在)
- foo.bar.com应该从bar.com/foo提供
- bar.bar.com应该从本地主机提供(bar.com/bar不存在)
- foobar.com应该从本地主机提供(foobar.com不存在)
- www.foobar.com应该从本地主机提供(foobar.com不存在)
- foo.foobar.com应该从本地主机提供(foobar.com不存在)
解决方案
此用途:mod_rewrite
,mod_proxy_http
和ofcourse mod_vhost_alias
。
ServerName my.domain
ServerAdmin admin@my.domain
<VirtualHost *:80>
ServerName localhost
VirtualDocumentRoot /var/www/localhost
</VirtualHost>
<VirtualHost *:80>
ServerName sub.domain
ServerAlias *.*.*
VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
RewriteCond /var/www/%2.%3 !-d
RewriteRule (.*) http://localhost/$1 [P]
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
RewriteCond /var/www/%2.%3/%1 !-d
RewriteCond /var/www/%2.%3/www !-d
RewriteRule (.*) http://localhost/$1 [P]
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
RewriteCond /var/www/%2.%3/%1 !-d
RewriteRule (.*) http://%2.%3/$1 [P]
</VirtualHost>
<VirtualHost *:80>
ServerName bare.domain
ServerAlias *.*
VirtualDocumentRoot /var/www/%-2.0.%-1.0/www
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)$ [NC]
RewriteCond /var/www/%1.%2 !-d [OR]
RewriteCond /var/www/%1.%2/www !-d
RewriteRule (.*) http://localhost/$1 [P]
</VirtualHost>
这是如何运作的?定义了三个虚拟主机:
本地主机
本地主机为默认主机。所有无法解决的请求均由localhost进行服务。设置从本地主机到任何域的符号链接就像将该站点设置为默认站点一样。
子域
sub.domain虚拟主机以的形式接受所有请求*.*.*
。默认情况下,所有请求均由/domain.com/sub
定义VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
。
倒退:
第一个RewriteRule
负责未知域,例如。domain.com
目录通过代理localhost网站不存在。
RewriteRule
当domain.com/sub
和domain.com/www
目录都不存在时,第二个也代理localhost 。
何时的第三个RewriteRule
代理不存在。我们知道确实存在,因为第二个重写块。domain.com
domain.com/sub
domain.com/www
裸域
nude.domain虚拟主机正在接受*.*
请求并为其提供服务/domain.com/www
在此处,RewriteRule
当domain.com
或domain.com/www
不存在时,will将代理到localhost 。
^ $%。* !!!
我在将所有这些标志$
和%
标志包裹起来时遇到一些麻烦RewriteCond
,RewriteRule
因此在这里我将对它们进行解释:
ServerAlias *.*.*
VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
RewriteCond /var/www/%2.%3/%1 !-d
RewriteRule (.*) http://%2.%3/$1 [P]
- 在
*
在ServerAlias
都只是通配符。
- 将
%n
在VirtualDocumentRoot
距离文档名称插值。
- 在
%n
第二RewriteCond
指选择(.*)
从第一RewriteCond
,例如。请求域的各个部分。
- 该
%n
在RewriteRule
做了。
- 中的表示
$1
在开头RewriteRule
的选择。它将捕获从域到请求URL中的所有内容。任何查询字符串都会由自动添加到url中。(.*)
RewriteRule
?
mod_proxy