Apache Directory Directive: Absolute Path vs DocumentRoot-Relative Path in VirtualHost Configuration


6 views

The Apache Directory directive accepts both absolute paths and paths relative to the server's filesystem root. While the documentation mentions "full path to a directory," the implementation is more flexible in practice.

<VirtualHost *:80>
    # Absolute path works
    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    # Also works when DocumentRoot is /var/www
    <Directory /html>
        Options -Indexes +FollowSymLinks
    </Directory>
</VirtualHost>

From testing various configurations:

  • Absolute paths always work as expected
  • Relative paths are resolved from filesystem root, not DocumentRoot
  • Best practice is to use absolute paths for clarity

The documentation shows both styles because:

  1. Historical reasons (older versions had slightly different behavior)
  2. Different use cases (server-wide vs vhost-specific configurations)
  3. Performance considerations (wider vs narrower directory matches)

For VirtualHosts, I recommend this pattern:

<VirtualHost *:443>
    DocumentRoot /srv/example.com/public
    
    # Base security restrictions
    <Directory />
        Options -Indexes -Includes
        AllowOverride None
    </Directory>
    
    # Site-specific permissions
    <Directory /srv/example.com/public>
        Options +FollowSymLinks -MultiViews
        AllowOverride FileInfo
        Require all granted
    </Directory>
</VirtualHost>

Watch for these configuration mistakes:

# Problematic - might not do what you expect
<Directory public_html>  
    # This looks relative but actually refers to /public_html
</Directory>

# Dangerous - over-permissive at root level
<Directory />
    Options All
    AllowOverride All
</Directory>

In Apache configuration, particularly within VirtualHost blocks, there's persistent ambiguity about whether Directory paths should be absolute or relative to DocumentRoot. The documentation contains contradictory examples that fuel this confusion:

<VirtualHost *:80>
    DocumentRoot /var/www/example
    # Which of these is correct?
    <Directory /var/www/example>
    <Directory />
    <Directory .>
</VirtualHost>

While the official documentation states "Directory-path is either the full path to a directory," real-world examples show both patterns:

  • Full absolute paths: <Directory /var/www/html>
  • Filesystem root paths: <Directory />

Through testing and examining Apache's source behavior, we observe:

# This works because it's absolute
<Directory /var/www/example/public>
    Options -Indexes +FollowSymLinks
</Directory>

# This works because it's filesystem root
<Directory />
    AllowOverride None
</Directory>

# This would FAIL - no relative path resolution
<Directory ./public>
    # Will not work as expected
</Directory>

Major distributions handle this differently. Here's a comparison:

# Debian/Ubuntu default:
<VirtualHost *:80>
    DocumentRoot /var/www/html
    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    <Directory /var/www/html>
        Options Indexes FollowSymLinks
    </Directory>
</VirtualHost>

# CentOS/RHEL default:
<VirtualHost *:80>
    DocumentRoot /var/www/html
    <Directory "/var/www/html">
        AllowOverride All
    </Directory>
</VirtualHost>

Using <Directory /> affects the entire filesystem, which requires careful permission settings:

# SECURITY BEST PRACTICE
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory /var/www>
    Require all granted
</Directory>

Use absolute paths when:

  • Configuring specific website directories
  • Working with multiple DocumentRoots
  • Need explicit path clarity

Use root path (/) when:

  • Setting global restrictions
  • Establishing baseline security policies
  • Working with aliased/symlinked paths

Check how Apache interprets your paths:

# Test configuration
apachectl -S
apachectl -t -D DUMP_RUN_CFG