Apache VirtualDocumentRoot as a variable

apache-2.4

Can I use the document root resulting from a VirtualDocumentRoot as a variable in other places in the same VirtualHost?

Take the following VirtualDocumentRoot for example:

VirtualDocumentRoot "/var/workspaces/%1"

The resulting document root from the hostname test.localhost is /var/workspaces/test. Which is also visible as the document root in the $_SERVER['DOCUMENT_ROOT'] in php.

So can I use the actual document root in a PutEnv or Define directive in the apache config? Is there a variable in the apache config with the actual document root?

edit:

I want to use this for a few different use cases.

I want to set a logging directory for all my applications, so I want to do something like this:

SetEnv LOG_DIR ${DOCUMENT_ROOT}/logs/

Or I want to point the php-fpm applications in the right direction:

ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9764${DOCUMENT_ROOT}/$1

Or set some different directives on a sub directory in the document root:

<Directory "${DOCUMENT_ROOT}/bin">

Best Answer

First, I'd like to point out that the desired state of your use cases might have certain security issues.

Why would you like to store logs inside DocumentRoot? This increases the risk of exposing logs to public. Of course you can prevent this with a new <Directory> directive, but it is easier to keep the logs on different directory. It's also more manageable in the perspective of directory permissions, considering Log Files Security Warning:

Anyone who can write to the directory where Apache httpd is writing a log file can almost certainly gain access to the uid that the server is started as, which is normally root. Do NOT give people write access to the directory the logs are stored in without being aware of the consequences; see the security tips document for details.

In addition, log files may contain information supplied directly by the client, without escaping. Therefore, it is possible for malicious clients to insert control-characters in the log files, so care must be taken in dealing with raw logs.

On the other hand, you cannot have separated log file for each virtual host if using mod_vhost_alias. While the motivation for using Dynamically Configured Mass Virtual Hosting is having only one "wildcard" VirtualHost container for all customer-*.example.com,

The main disadvantage is that you cannot have a different log file for each virtual host; however, if you have many virtual hosts, doing this can be a bad idea anyway, because of the number of file descriptors needed. It is better to log to a pipe or a fifo, and arrange for the process at the other end to split up the log files into one per virtual host. One example of such a process can be found in the split-logfile utility.


It seems that in this case the setup needs to meet these requirements:

  • you have limited amount of these "workspaces"
  • you would like to have the exactly same configuration for every workspace
  • the configuration needs to be customized for your special needs
  • you would like to make it easier to add more workspaces without adding new VirtualHost containers.

Thus, considering all the limitations with mod_vhost_alias, I'd suggest abandoning it and using mod_macro instead, as it would meet the requirements and it's much more flexible.

An example macro with all the examples from your question (even the not recommended LOG_DIR):

<Macro Workspace $workspace>
  <VirtualHost *:80>
    ServerName $workspace.localhost
    DocumentRoot "/var/workspaces/$workspace"

    SetEnv LOG_DIR "/var/workspaces/$workspace/logs/"

    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9764/var/workspaces/$workspace/$1

    <Directory "/var/workspaces/$workspace">
      Require all granted
    </Directory>

    <Directory "/var/workspaces/$workspace/logs">
      Require all denied
    </Directory>
  </VirtualHost>
</Macro>

Now, you can add all the workspaces with:

Use Workspace test
Use Workspace another
Use Workspace third

Unlike with mod_vhost_alias you can still have a custom domain for every workspace. Just modify <Macro Workspace $workspace $hostname> and ServerName $hostname and you can use the macro with Use Workspace testwithdomain example.com.