Contexts and Merge Order

Configuration Contexts and Merge Order

A directive can live in four contexts: server config, virtual host, directory (<Directory>, <Files>, <Location>, <If>) and .htaccess. For each request Apache 129 merges the matching sections in a fixed order, and a later section overrides an earlier one. The order depends on the section type, not on where the section sits in the file; within each step, server-wide sections apply before the virtual host's.

The order in which Apache merges configuration sections for one request
The order in which Apache merges configuration sections for one request

To prove the order, each section below appends its name to a response header, written backward:

Five section types written in reverse order, plus one server-wide sectionXML
<VirtualHost *:8101>
  ServerName site-a.example
  DocumentRoot /var/www/site-a
  <If "%{QUERY_STRING} =~ /debug/">
    Header append X-Order "If"
  </If>
  <Location "/docs">
    Header append X-Order "Location"
  </Location>
  <Files "*.html">
    Header append X-Order "Files"
  </Files>
  <DirectoryMatch "^/var/www/site-a/docs">
    Header append X-Order "DirectoryMatch"
  </DirectoryMatch>
  <Directory "/var/www/site-a">
    AllowOverride FileInfo
    Header append X-Order "Directory"
  </Directory>
</VirtualHost>
<Directory "/var/www/site-a">
  Header append X-Order "Directory (server)"
</Directory>

A one-line docs/.htaccess adds Header append X-Order ".htaccess". With mod_headers enabled (Modules), three requests show which sections matched, in order:

Reading the merge order from the responseShell
curl -sI -H 'Host: site-a.example' 'localhost:8101/docs/page.html?debug=1' | grep X-Order
curl -sI -H 'Host: site-a.example' localhost:8101/docs/page.html | grep X-Order
curl -sI -H 'Host: site-a.example' localhost:8101/index.html | grep X-Order
Output
X-Order: Directory (server), Directory, .htaccess, DirectoryMatch, Files, Location, If
X-Order: Directory (server), Directory, .htaccess, DirectoryMatch, Files, Location
X-Order: Directory (server), Directory, Files

The server-wide <Directory> ran first although it comes last in the file, and .htaccess overrode <Directory> but lost to every later step. Because <Location> and <If> merge last, a Require all granted in either silently cancels a <Directory> restriction, so keep access control in filesystem sections (Directory, Files, Location). Merging and Inheritance extends this to nested .htaccess files.