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


23 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>