The Directory/Location Context Model & .htaccess In Depth
Apache In Depth
Chapter 3 · The Directory/Location Context Model & .htaccess In Depth
Web Servers Fundamentals Chapter 3 introduced .htaccess conceptually: a per-directory override file, checked on every request, with a real filesystem-scan cost in exchange for letting someone without access to the main config make changes. This chapter goes deep on the two things that actually determine what a given .htaccess file can do and how it interacts with everything else: AllowOverride's real granularity, and the actual merge order across every context type Apache supports.
AllowOverride: What .htaccess Is Actually Allowed to Touch
AllowOverride is not just an on/off switch — it names exactly which groups of directives a .htaccess file in that directory is permitted to set. None disables .htaccess checking entirely for that directory tree (and is the real fix for Fundamentals' own filesystem-scan cost, since Apache then knows not to look at all). All permits every group — broad and rarely the right default. In between, five named groups exist: AuthConfig (authentication directives — AuthType, AuthName, Require), FileInfo (ErrorDocument, and — notably — every mod_rewrite directive), Indexes (IndexOptions, DirectoryIndex, IndexIgnore), Limit (Require/Order/Allow/Deny access-control directives), and Options[=...] (the Options directive itself).
AllowOverride Indexes and Options Indexes are two completely different things that happen to share a name. The AllowOverride group called Indexes controls whether .htaccess is even allowed to set directory-listing-related directives at all (IndexOptions, DirectoryIndex). The Options value called Indexes is the actual setting that turns directory listing on. Granting AllowOverride Indexes does not itself enable directory listing — a .htaccess file in that directory would still need its own Options +Indexes or Options -Indexes line, and that specific line falls under the separate Options override group, not this one.
The Real Merge Order: Directory → .htaccess → Files → Location
Apache applies contexts in a fixed order, and later contexts can override directives set by earlier ones — but this is a merge, not a wholesale replacement. Directives a later context doesn't mention still carry over from the broader context that set them. The real order: (1) the main server config and any matching <VirtualHost>, (2) every <Directory> block that matches the requested path, evaluated from the least specific path to the most specific, followed by that most specific directory's own .htaccess file (if AllowOverride permits it), (3) <Files>/<FilesMatch>, and finally (4) <Location>/<LocationMatch>.
A request under /private merges both blocks: the more specific /private context isn't a full replacement of the parent, so FollowSymLinks is still inherited from the parent since /private never mentions it — only Indexes is actually touched, and the leading - means "remove this specific option," not "replace the whole Options list." The end result for /private is FollowSymLinks on, Indexes off, plus the new IP restriction — a genuine merge across two contexts, not the child context overwriting the parent's settings wholesale.
A Worked .htaccess Example
This one file actually needs two separate AllowOverride groups to work at all: Options (for the Options -Indexes line) and FileInfo (which covers both ErrorDocument and every mod_rewrite directive, including RewriteEngine and RewriteRule). A directory whose AllowOverride is set to just AuthConfig would reject every line in this file.
| AllowOverride group | Covers | Typical use |
|---|---|---|
| AuthConfig | AuthType, AuthName, Require | Per-directory login restriction |
| FileInfo | ErrorDocument, all mod_rewrite directives | Custom error pages, URL rewriting |
| Indexes | IndexOptions, DirectoryIndex, IndexIgnore | Directory-listing appearance (not whether it's on) |
| Limit | Require/Order/Allow/Deny | IP-based access restriction |
| Options[=...] | The Options directive itself | Turning directory listing, symlink-following, etc. on/off |
AllowOverride None everywhere it isn't genuinely needed is one of the standard hardening recommendations Chapter 8 covers in depth — it isn't just a performance win from skipping the per-request filesystem scan, it also closes off an entire class of misconfiguration risk from a compromised or careless .htaccess file, since there's nothing left for one to override.
Hands-On Exercises
Using the two nested <Directory> blocks in this chapter's own merge-order example (Options Indexes FollowSymLinks on the parent, Options -Indexes on /private), state the effective Options settings a request to /private actually ends up with, and explain why FollowSymLinks survives even though /private never mentions it.
📄 View solutionA directory has AllowOverride set to AuthConfig only, but its .htaccess file (this chapter's own worked example) contains RewriteEngine/RewriteRule and Options directives. Using this chapter's own material, explain what actually happens when a request hits that directory — not just "it won't work," but the specific real behavior.
📄 View solutionExplain, in your own words, why "AllowOverride Indexes" does not by itself turn on directory listing, using this chapter's own warning box about the two different things named "Indexes."
📄 View solutionChapter 3 Quick Reference
- AllowOverride —
None(no .htaccess checking),All(everything), or a named group:AuthConfig,FileInfo,Indexes,Limit,Options - The
AllowOverride Indexesgroup and theOptions Indexesvalue are different things that share a name — one permits, the other enables - Real merge order: main config/VirtualHost →
<Directory>(least to most specific) +.htaccess→<Files>→<Location>— a merge, not a full replacement, at every step - A directive a
.htaccessfile isn't permitted to set byAllowOverridedoesn't fail silently AllowOverride Nonewherever genuinely possible is both a performance and a hardening win — expanded on in Chapter 8