Apache Virtual Hosts: How to Share Directory Directives Across Multiple Domains Efficiently


2 views

When managing multiple virtual hosts in Apache that share similar configurations, particularly when they use the same DocumentRoot and directory settings, repetitive configuration becomes inevitable. Here's a common scenario many developers face:

<VirtualHost *:80>
  ServerName domain1.com
  DocumentRoot "/var/www/shared/web"
  <Directory "/var/www/shared/web">
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

<VirtualHost *:80>
  ServerName domain2.com 
  DocumentRoot "/var/www/shared/web"
  <Directory "/var/www/shared/web">
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

Just like in programming, we should apply the DRY (Don't Repeat Yourself) principle to Apache configurations. There are several ways to achieve this:

1. Using Include Directive

Create a separate file (e.g., shared_directories.conf) containing common Directory directives:

# shared_directories.conf
<Directory "/var/www/shared/web">
  AllowOverride All
  Require all granted
</Directory>

<Directory "/usr/share/pear/data/symfony/web/sf">
  AllowOverride All
  Require all granted
</Directory>

Then include it in each VirtualHost:

<VirtualHost *:80>
  ServerName domain1.com
  DocumentRoot "/var/www/shared/web"
  Include /path/to/shared_directories.conf
</VirtualHost>

2. Using Macros (mod_macro)

For more advanced scenarios, you can use mod_macro to create configuration templates:

<Macro SharedHost $name>
  <VirtualHost *:80>
    ServerName $name
    DocumentRoot "/var/www/shared/web"
    <Directory "/var/www/shared/web">
      AllowOverride All
      Require all granted
    </Directory>
  </VirtualHost>
</Macro>

Use SharedHost domain1.com
Use SharedHost domain2.com

While these approaches reduce configuration duplication, keep in mind:

  • Apache still processes each Directory directive separately for each VirtualHost
  • Include files are read at server startup/reload
  • Too many includes might make debugging more difficult

Here's how I typically structure this for a multi-domain Symfony project:

# apache2/sites-available/shared_dirs.conf
<Directory "/var/www/symfony_project/web">
  Options FollowSymLinks
  AllowOverride None
  Require all granted
  FallbackResource /index.php
</Directory>

<Directory "/var/www/symfony_project/web/bundles">
  AllowOverride All
  Require all granted
</Directory>

# apache2/sites-available/domain1.conf
<VirtualHost *:80>
  ServerName domain1.com
  Include /etc/apache2/sites-available/shared_dirs.conf
  DocumentRoot "/var/www/symfony_project/web"
  ErrorLog ${APACHE_LOG_DIR}/domain1_error.log
  CustomLog ${APACHE_LOG_DIR}/domain1_access.log combined
</VirtualHost>

When managing multiple domains with identical directory configurations in Apache, we often face redundant blocks across VirtualHost entries. Consider this typical scenario:

<VirtualHost *:80>
  ServerName domain1.com
  DocumentRoot "/var/www/srs/web"
  <Directory "/var/www/srs/web">
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

<VirtualHost *:80>
  ServerName domain2.com
  DocumentRoot "/var/www/srs/web"
  <Directory "/var/www/srs/web">
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

Instead of repeating identical configurations, we can move the shared directives to the main server context (httpd.conf or apache2.conf):

# In main Apache configuration
<Directory "/var/www/srs/web">
  AllowOverride All
  Require all granted
</Directory>

# Individual VirtualHosts become cleaner
<VirtualHost *:80>
  ServerName domain1.com
  DocumentRoot "/var/www/srs/web"
</VirtualHost>

<VirtualHost *:80>
  ServerName domain2.com
  DocumentRoot "/var/www/srs/web"
</VirtualHost>

For more complex scenarios, consider using Include directives to manage shared configurations:

# Create shared.conf
<Directory "/var/www/srs/web">
  Options FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>

# In VirtualHost definitions
<VirtualHost *:80>
  ServerName domain1.com
  DocumentRoot "/var/www/srs/web"
  Include /path/to/shared.conf
</VirtualHost>
  • Directory directives in VirtualHost blocks override main configuration
  • Order of evaluation matters: main config → VirtualHost → .htaccess
  • Always test configuration with apachectl configtest
  • For security, restrict Directory directives to necessary paths only

Here's how we handle shared assets in a Symfony project:

# Shared configuration
<Directory "/usr/share/pear/data/symfony/web/sf">
  AllowOverride None
  Require all granted
</Directory>

<VirtualHost *:80>
  ServerName api.example.com
  DocumentRoot "/var/www/srs/web"
  Alias /sf /usr/share/pear/data/symfony/web/sf
</VirtualHost>

<VirtualHost *:80>
  ServerName admin.example.com
  DocumentRoot "/var/www/srs/web"
  Alias /sf /usr/share/pear/data/symfony/web/sf
</VirtualHost>