Configuration model
Apache HTTP Server reads a single merged configuration tree built from the main file (often httpd.conf or apache2.conf) plus Include / IncludeOptional fragments. IncludeOptional skips missing paths without error—useful for distro drop-ins under conf.d/. The effective tree is produced at startup (or reload); there is no per-request re-parse of the main files, but .htaccess is re-read along each URL path segment when allowed.
Directive contexts (why order and placement matter)
Every directive declares which contexts it is legal in: server config, virtual host, directory, .htaccess, and others. A directive in an illegal context fails httpd -t. More importantly, merge order determines which block wins when multiple sections apply: generally inner (more specific) directory context overrides outer, subject to module-specific merge rules documented per directive.
| Context | Typical file location | Notes |
|---|---|---|
| Server config | Main conf, conf.d/*.conf | Global defaults: ServerRoot, Listen, global modules |
| VirtualHost | sites-enabled/*.conf | Per-IP/name binding; first matching vhost for a socket pair is the default if no other match |
| Directory / Location / Files | Inside vhost or server | <Directory> maps to filesystem paths; <Location> maps to URL prefixes independent of disk |
| .htaccess | Per-directory on disk | Parsed only if AllowOverride is not None; adds per-request stat() cost up the path |
ServerRoot, DocumentRoot, and path semantics
ServerRoot is the anchor for relative paths in configuration (modules, logs, run files). DocumentRoot is only the default URL-to-filesystem mapping for a vhost; Alias, RewriteRule, and reverse proxies can serve content from elsewhere. The runtime user (User/Group on Unix) must have search bit on each directory component leading to files and appropriate read/execute bits on scripts executed as CGI.
Modules and the request hook chain
Apache processes requests through a hook API: each module registers handlers in phases (URL translation, header parsing, access control, content generation, logging). LoadModule order rarely changes hook order within a phase—that is defined by module priorities—but which modules are loaded determines available directives. Use httpd -M / apache2ctl -M to list static and shared modules; use httpd -l for compile-time static modules only.
Apache 2.4 on major distros ships dynamic modules (LoadModule from mods-available symlinked into mods-enabled on Debian). Wrapping optional blocks in <IfModule mod_foo.c> prevents startup failure if a module is absent, but can hide misconfiguration—prefer explicit packaging dependencies in automation.
MPM architecture (prefork, worker, event)
The Multi-Processing Module determines how connections map to processes and threads:
- prefork: one OS process per active connection at steady state (model prior to threads). Highest memory footprint per connection; still required for some
mod_phpdeployments that are not thread-safe. - worker: hybrid—few processes, each with a fixed thread pool. Better concurrency than prefork for keep-alive workloads.
- event (recommended default on modern distros when not using mod_php): like worker, but a listener thread accepts connections while worker threads handle requests; long-lived blocked connections can be offloaded so threads return to the pool faster (implementation details vary by patch level—consult your minor version notes).
Tune ServerLimit, MaxRequestWorkers (formerly MaxClients), ThreadsPerChild, and AsyncRequestWorkerFactor (event) together. Exceeding RAM per thread stack × worker count causes thrashing or OOM kills at the OS level—profile with realistic TLS and keep-alive.
Authorization and authentication (2.4 model)
Apache 2.4 replaced legacy Order allow,deny with mod_authz_core Require directives inside <RequireAny>, <RequireAll>, or <RequireNone> containers. Mixing old and new directives in the same scope can yield surprising merges—migrate fully to Require and remove Order/Allow/Deny when upgrading legacy configs.
Keep-Alive, timeouts, and slowloris-class pressure
KeepAlive On amortizes TLS handshakes but holds sockets longer. Pair MaxKeepAliveRequests and KeepAliveTimeout with reverse-proxy timeouts upstream. Timeout governs several blocking read/write waits; lowering it aggressively can break large uploads. For request-line / header limits, see LimitRequestLine, LimitRequestFieldSize, and LimitRequestFields—relevant when mitigating oversized header attacks without breaking legitimate clients behind corporate gateways.
Logging: ErrorLog, LogLevel, CustomLog
ErrorLog accepts local paths, syslog targets, or pipe programs. LogLevel can be scoped per module: LogLevel info ssl:warn reduces TLS noise while keeping core informative. Access logging uses CustomLog with a LogFormat nickname; common combined formats omit TLS cipher and TLS protocol—add %{SSL_PROTOCOL}x / %{SSL_CIPHER}x when mod_ssl is present for forensics. Pipe to rotatelike tools carefully: blocking log processors can stall workers.
Behind reverse proxies and CDNs
When Apache is not the TCP edge, use mod_remoteip (or equivalent) so internal access control and logging see the original client IP from trusted RemoteIPInternalProxy lists. Misconfiguration here breaks IP-based Require ip rules and distorts analytics—validate with controlled tests. Conceptual background: X-Forwarded-For semantics.
Enterprise and hardening notes
On RHEL-family systems, SELinux applies httpd_sys_content_t and related types to content paths; a correct DocumentRoot with wrong SELinux context yields permission errors unrelated to POSIX modes—use semanage fcontext / restorecon in change-managed pipelines. Ship ErrorLog and CustomLog to centralized logging with field redaction for query strings that may contain session tokens. CIS / STIG baselines often recommend disabling directory indexes, removing server signature leakage (ServerTokens Prod, ServerSignature Off), and eliminating unnecessary modules to reduce attack surface.
Related articles
Apache virtual hosts, .htaccess configuration, Apache SSL, performance tuning, common errors, and nginx vs Apache for architectural comparison.