Search code examples
apachemod-rewritevirtual-hostsmod-vhost-alias

Mass virtual hosting with Apache 2.4


I would like to use the value set by VirtualDocumentRoot in a RewriteRule.

The Apache documentation says:

The other thing to determine is the document root (configured with DocumentRoot and available to CGI scripts via the DOCUMENT_ROOT environment variable). In a normal configuration, this is used by the core module when mapping URIs to filenames, but when the server is configured to do dynamic virtual hosting, that job must be taken over by another module (either mod_vhost_alias or mod_rewrite), which has a different way of doing the mapping. Neither of these modules is responsible for setting the DOCUMENT_ROOT environment variable so if any CGIs or SSI documents make use of it, they will get a misleading value.

Refering to the documentation, it seems I won't be able to use %{DOCUMENT_ROOT} in RewriteRule. But after looking for alternative solutions, I found this ticket (title: DOCUMENT_ROOT environment variable set incorrectly with VirtualDocumentRoot) saying it has been “fixed in 2.4.1”.

I am using the latest (stable) version of Apache:

$ httpd -v
Server version: Apache/2.4.9 (Unix)
Server built:   Jun 18 2014 03:07:48

... but it doesn't seem to work for me. When testing, %{DOCUMENT_ROOT} has the default value set by DocumentRoot in httpd.conf. I would like %{DOCUMENT_ROOT} (or any other variable I could use) to be dynamically set by VirtualDocumentRoot.

Here is what I would like to use in httpd-vhosts.conf:

<VirtualHost *:8080>
    ServerName dev
    ServerAlias *.dev

    VirtualDocumentRoot "/usr/local/var/www/.dev/%-2+"

    RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/$1" [P]
</VirtualHost>

Is there a solution?


Solution

  • After having looked in many directions with @John Auld (thanks for your time and help), I have finally found a solution. As I said in a previous comment, it is not 100% perfect but good enough for me.

    For clarity's sake, here is what I wanted to have in httpd-vhosts.conf:

    <VirtualHost *:8080>
        ServerName dev
        ServerAlias *.dev
    
        VirtualDocumentRoot "/usr/local/var/www/.dev/%-2+"
    
        RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000%{DOCUMENT_ROOT}/$1" [P]
    </VirtualHost>
    

    And here is what I've come up with:

    <VirtualHost *:8080>
        ServerName dev
        ServerAlias *.dev
    
        VirtualDocumentRoot "/usr/local/var/www/.dev/%-2/%-3"
    
        RewriteCond %{SERVER_NAME} (?:([^.]+)\.)?([^.]+)\.dev
        RewriteRule ^/(.*\.php(/.*)?)$ "fcgi://127.0.0.1:9000/usr/local/var/www/.dev/%2/${:%1|www}/$1" [P]
    </VirtualHost>
    

    I use RewriteCond to capture parts of %{SERVER_NAME} and reuse them in RewriteRule.

    There are two capturing groups: subdomain (%1) and domain (%2). The subdomain is optional so I use the syntax ${map:value|default} to set a default value for the subdomain when empty.

    VirtualDocumentRoot has its own default value when a part (%N.M) is not available. As said in the documentation:

    If N or M is greater than the number of parts available a single underscore is interpolated.

    That's why I had to use a little "trick" to make it work with an optional subdomain:

    ln -sfv /path/to/the/project/www /path/to/the/project/_
    

    If you think of a way to do it "config only", leave a comment and I will edit my answer with your contribution.