通用的大规模虚拟主机配置会导致每个虚拟主机请求出现 404 状态代码

通用的大规模虚拟主机配置会导致每个虚拟主机请求出现 404 状态代码

我正在尝试使用 ServerAlias 设置具有大量子域的 apache 2.4 服务器。主域的基本配置工作得很好(主域 => 200,所有子域 => 404):

UseCanonicalName Off

<VirtualHost example.com>
        ServerName example.com
        ServerAlias www.example.com
        VirtualDocumentRoot "/var/www/vhosts/example.com/httpdocs"
        DirectoryIndex index.php index.html

        <Directory />
                Options +Indexes +FollowSymLinks +Includes
                <IfModule !mod_access_compat.c>
                        Require all granted
                </IfModule>
                <IfModule mod_access_compat.c>
                        Order allow,deny
                        Allow from all
                </IfModule>
                AllowOverride All
        </Directory>
</VirtualHost>

但是,当我为通用虚拟主机设置添加行时,Web 服务器会在每个虚拟主机(子域)请求上返回 404 状态代码:

UseCanonicalName Off

<VirtualHost example.com>
        ServerName example.com
        ServerAlias www.example.com
        VirtualDocumentRoot "/var/www/vhosts/example.com/httpdocs"
        DirectoryIndex index.php index.html
        ServerAlias *.example.com
        VirtualDocumentRoot "/var/www/vhosts/example.com/%1.0"
        DirectoryIndex index.php index.html

        <Directory />
                Options +Indexes +FollowSymLinks +Includes
                <IfModule !mod_access_compat.c>
                        Require all granted
                </IfModule>
                <IfModule mod_access_compat.c>
                        Order allow,deny
                        Allow from all
                </IfModule>
                AllowOverride All
        </Directory>
</VirtualHost>

我认为它必须对正确的文件夹路径做一些事情。文件夹路径始终如下所示:

/var/www/vhosts/maindomain.com/subdomain.maindomain.com

我需要的只是一个与主域和与之关联的通用子域相匹配的配置。所以,

www.example.com
example.com

匹配文件夹路径:

/var/www/vhosts/example.com/httpdocs

ci.example.com
tracker.example.com
other.example.com

应与其文件夹路径匹配,如下所示:

/var/www/vhosts/example.com/ci.example.com
/var/www/vhosts/example.com/tracker.example.com
/var/www/vhosts/example.com/other.example.com

另外,由于某种奇怪的原因,如果我将其更改为%0.0子域路径,则子域可以工作,但主域却不能。因此,使用它时,情况正好相反。主域 => 404,所有子域 => 200。

我在 apache 2.4 文档中找到了文件夹名称的魔术字符串文字的解释:http://httpd.apache.org/docs/2.4/mod/mod_vhost_alias.html 但它并没有解决我的问题,反而让我越来越困惑......

Web 服务器在 openSUSE 42.2 最低版本下运行。正如您可能已经建议的那样,此处的真实域名已更改为example.com.对这个问题的任何帮助都会很棒。

编辑:正如我在下面对第一个答案的评论中所说,我需要一个解决方案,不一定需要RewriteRule虚拟主机配置中的任何解决方案。因为我使用的是 php 系统,它们确实有自己的(有时非常复杂)RewriteRule,所以我不想因为这些.htaccess东西而陷入麻烦。但除此之外的任何其他选择cgi都是可能的。是的,符号链接支持已启用(或可以启用)。


编辑:

符号链接示例帮助我了解了基本概念。经过一番反思,我想到了下面这个解决方案。第一个发现的规则始终适用,所以它对我有用:

UseCanonicalName Off
<VirtualHost *:80>
        DocumentRoot "/var/www/vhosts/example.com/httpdocs"
        ServerName www.example.com
        ServerAlias example.com
        <Directory />
                Options Indexes FollowSymLinks Includes ExecCGI
                AllowOverride All
                Require all granted
                Allow from all
        </Directory>
</VirtualHost>

<VirtualHost *:80>
        DocumentRoot "/var/www/vhosts/example.com/httpdocs"
        ServerName example.com
        ServerAlias *.example.com
        VirtualDocumentRoot "/var/www/vhosts/example.com/%1"
        <Directory />
                Options Indexes FollowSymLinks Includes ExecCGI
                AllowOverride All
                Require all granted
                Allow from all
        </Directory>
</VirtualHost>

apachectl -tapachectl -S说这没关系。测试并有效! :-)

答案1

尝试

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/vhosts/example.com/httpdocs
    ServerAlias *.example.com
    VirtualDocumentRoot /var/www/vhosts/example.com/%0
</VirtualHost>

这显然不包括整个配置,但它应该使您的通配符子域正常工作。

接下来,我会将所有请求重定向www.example.comexample.com。最简单的方法可能是使用 htaccess 文件/var/www/vhosts/example.com/www.example.com

或者,如果您打开了符号链接,则可以符号链接/var/www/vhosts/example.com/www.example.com/var/www/vhosts/example.com/httpdocs

编辑:

如果您不想在.htaccess.尝试这个:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/vhosts/example.com/httpdocs
    ServerAlias *.example.com
    VirtualDocumentRoot /var/www/vhosts/example.com/%0
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www.example.com
    RewriteRule ^/(.*)$ http://example.com/$1 [L,R=301]
</VirtualHost>

我不知道有什么方法可以在没有某种重定向的情况下做到这一点。另外,将非 www 重定向到 www 或将 www 重定向到非 www 是一种很好的做法。如果您打算进行任何 SEO 工作,那么拥有与您的网站本质上重复的内容将会是一种损害。

答案2

我为自己写了一个脚本 - 这对我有用:)

但在阅读我的脚本之前 - 我给你的提示是不要使用

<VirtualHost example.com>
....
</VirtualHost>

而是使用:<VirtualHost *:80><VirtualHost *>来开始您的 VirtualHost 条目。

注意:我主要在 AIX 上工作 - 所以我使用 ksh 作为 shell。这应该适用于 /bin/sh 或 /bin/bash。

Syntax:
vhost.ksh <ServrName> [ServerAlias1] [... ServerAliasN]

#!/usr/bin/ksh
# Copyright AIXTOOLS.NET, 2014
# This script creates a vhost template
# under the assumption that the site might be served by multiple hosts
# the logs are put into a sub-directory
# ${SITEroot}/logs/LOGNAME.$host
site=$1
shift
alias=$*
HOST=`hostname -s`
SITE=/var/httpd/${site}
LOGDIR=${SITE}/logs

cat -<<EOF1
# AIXTOOLS.NET vhost.ksh output
# VirtualHost template for ${site}
# SITEBASE=${SITE}
# LOGDIR=${LOGDIR}

<VirtualHost *:80>
     ServerName  ${site}
EOF1
for name in ${alias}
do
print "    ServerAlias  ${name}"
done

cat - <<EOF2

DocumentRoot "${SITE}/htdocs"

<Directory "/var/httpd/${site}/htdocs">
    Options Indexes FollowSymLinks Includes
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

#Logs for ${site}
# combined is chosen as default to support awstats reporting
    CustomLog "${LOGDIR}/access_log.${HOST}" combined
#    ErrorLog "${LOGDIR}/error_log.${HOST}"
# You can consider using different "localN" syslogs to split different vhosts
# should you need that
    ErrorLog syslog:user
#    LogLevel alert rewrite:trace3
#    LogLevel alert
#    RewriteLog "/var/httpd/${site}/logs/rewrite.log"
#    RewriteLogLevel 0
</VirtualHost>
EOF2

相关内容