Apache HTTP Server

Apache HTTP Server (commonly referred to as “Apache”) is one of the most widely used web servers in the world. It is maintained by the Apache Software Foundation and offers robust, flexible, and highly configurable capabilities for serving static and dynamic content. Over the decades, Apache has become a cornerstone of the modern web, powering websites of all sizes, from personal blogs to large enterprise systems. This guide explores Apache’s architecture, configuration files, modules, and common tasks. ASCII diagrams provide insight into request flows and how Apache interacts with operating system resources and other services.

Core Architecture and Concepts

Process Models (MPMs)

Apache’s architecture revolves around “Multi-Processing Modules” (MPMs) that define how it manages child processes or threads to handle incoming requests. Common MPMs include:

  • Prefork: Spawns multiple child processes, each handling one request at a time using a single thread. Historically favored for compatibility with non-thread-safe modules (like certain older PHP modules).
  • Worker: Uses a pool of child processes, each containing multiple threads, which can handle more requests concurrently with fewer system processes.
  • Event: Similar to Worker but optimizes keep-alive connections by assigning them to dedicated threads, potentially reducing thread blocking.

A simplified diagram of how Apache might handle connections using the Worker MPM:

   +----------------+    (Incoming Connections)
   |   Internet     | ------------+
   | (Clients)      |            |
   +--------+-------+            |
            |                    |
            v                    v
       +-----------+    +-----------+    +-----------+
       |  Apache   |    |  Apache   |    |  Apache   |
       |  Parent   |... |  Child1   |..  |  Child2   |...
       |  Process  |    +-----+-----+    +-----+-----+
       +-----------+          |               |
                   (Thread 1,2,...n)    (Thread 1,2,...n)

In this diagram, the main Apache parent process spawns child processes (in Worker/Event MPM) that each manage a pool of threads. Each thread can handle one client connection at a time.

Installation and Directory Structure

Installation

How you install Apache depends on your OS:

  • Debian/Ubuntu:
    sudo apt-get update
    sudo apt-get install apache2
  • CentOS/Red Hat:
    sudo yum install httpd
  • macOS (Homebrew):
    brew install httpd

Once installed, Apache typically runs as a service (e.g., apache2.service or httpd.service). You can start, stop, or restart it via your distribution’s service manager (systemctl, service, etc.).

Key Directories and Files

Although file paths vary across distributions, a general layout might look like this:

/etc/apache2/           (Debian/Ubuntu) or /etc/httpd/ (Red Hat/CentOS)
├── apache2.conf        or httpd.conf (Main config file)
├── mods-available/     or modules.d/
├── mods-enabled/
├── sites-available/
├── sites-enabled/
└── conf.d/             (Additional config fragments)
  • httpd.conf / apache2.conf: Primary configuration file.
  • sites-available/ and sites-enabled/: Where virtual host configurations are stored (Debian/Ubuntu style).
  • mods-available/ and mods-enabled/: Scripts or configuration files that load modules.
  • conf.d/: Additional global configuration snippets.

Core Configuration Files

Main Configuration (httpd.conf or apache2.conf)

This file sets up fundamental directives like ServerRoot, ServerAdmin, ServerName, MPM settings, and includes references to other config files. For example:

ServerRoot "/etc/httpd"
ServerAdmin admin@example.com
ServerName www.example.com
Listen 80
 
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule rewrite_module modules/mod_rewrite.so
# ...
Include conf.modules.d/*.conf
Include conf.d/*.conf

Virtual Hosts

Virtual hosts allow Apache to serve different websites or applications from a single server instance by matching domain names or IP addresses. A common pattern on Debian-based systems is to have site-specific config files in sites-available/, then symlink them into sites-enabled/. A simple mywebsite.conf might look like:

<VirtualHost *:80>
    ServerName mywebsite.com
    ServerAlias www.mywebsite.com
    DocumentRoot /var/www/mywebsite
 
    <Directory /var/www/mywebsite>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
 
    ErrorLog  /var/log/apache2/mywebsite_error.log
    CustomLog /var/log/apache2/mywebsite_access.log combined
</VirtualHost>

Then enable it (Debian/Ubuntu style) via:

sudo a2ensite mywebsite
sudo systemctl reload apache2

On Red Hat-based systems, you manually include it in httpd.conf or place it in conf.d/, ensuring NameVirtualHost *:80 is set if needed (for older versions).

Modules (mods-available / mods-enabled)

Apache’s functionality can be extended with modules such as mod_rewrite (URL rewriting), mod_ssl (SSL/TLS), mod_proxy (reverse proxy), etc.

On Debian-based systems, commands like a2enmod and a2dismod enable or disable modules. On Red Hat-based systems, you typically edit httpd.conf or a related file to load them (e.g., LoadModule rewrite_module modules/mod_rewrite.so).

Serving Static Files

Apache can serve static assets like HTML, CSS, images, and more. By default, the DocumentRoot directive designates the root directory for static content. For instance, if DocumentRoot is /var/www/html, then requests to http://server/index.html map to /var/www/html/index.html.

<VirtualHost *:80>
    DocumentRoot /var/www/html
    <Directory "/var/www/html">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

Dynamic Content with Modules

mod_php or PHP-FPM

To serve PHP pages, Apache traditionally used mod_php which runs PHP code within the Apache worker processes. However, a more modern approach is using mod_proxy_fcgi with PHP-FPM:

<VirtualHost *:80>
    ServerName phpexample.com
    DocumentRoot /var/www/phpapp
 
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</VirtualHost>

In this case, .php requests are forwarded through a FastCGI socket managed by PHP-FPM. This separation can offer better security and performance than older mod_php approaches.

mod_wsgi (Python)

For Python-based applications (e.g., Django or Flask), mod_wsgi is commonly used:

<VirtualHost *:80>
    ServerName pythonapp.com
    WSGIDaemonProcess myapp python-path=/var/www/myapp
    WSGIScriptAlias / /var/www/myapp/myapp/wsgi.py process-group=myapp
 
    <Directory /var/www/myapp/myapp>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>

mod_jk or AJP for Java (Tomcat)

When integrating with Tomcat, you might use the AJP connector and mod_jk. The configuration references a workers.properties file specifying the Tomcat backend.

Reverse Proxy and Load Balancing

Apache’s mod_proxy can forward requests to another server or service, acting as a reverse proxy. For example:

<VirtualHost *:80>
    ServerName proxyexample.com
 
    ProxyPreserveHost On
    ProxyRequests Off
 
    <Location />
        ProxyPass http://127.0.0.1:3000/
        ProxyPassReverse http://127.0.0.1:3000/
    </Location>
</VirtualHost>

Requests to http://proxyexample.com/ are internally proxied to a local service on port 3000. For load balancing multiple backends, use mod_proxy_balancer:

<Proxy balancer://mycluster>
    BalancerMember http://192.168.0.10:3000
    BalancerMember http://192.168.0.11:3000
</Proxy>
 
<VirtualHost *:80>
    ProxyPreserveHost On
 
    <Location /api/>
        ProxyPass balancer://mycluster/
        ProxyPassReverse balancer://mycluster/
    </Location>
</VirtualHost>

Apache can distribute requests among those two servers using the default (round-robin) or other algorithms.

SSL/TLS Configuration with mod_ssl

Enable HTTPS to secure traffic. On many systems, mod_ssl is included but may need enabling (a2enmod ssl on Debian/Ubuntu). Then configure a virtual host on port 443:

<VirtualHost *:443>
    ServerName secure.example.com
    SSLEngine on
    SSLCertificateFile    /etc/ssl/certs/example.crt
    SSLCertificateKeyFile /etc/ssl/private/example.key
 
    DocumentRoot /var/www/secure
    <Directory "/var/www/secure">
        Require all granted
    </Directory>
</VirtualHost>

You can enforce HTTP to HTTPS redirection:

<VirtualHost *:80>
    ServerName secure.example.com
    Redirect / https://secure.example.com/
</VirtualHost>

Logging and Monitoring

Apache logs requests and errors in typically two separate files:

  • Access Log: By default, stored in /var/log/apache2/access.log or /var/log/httpd/access_log. Captures each request line, status code, bytes sent, user agent, etc.
  • Error Log: /var/log/apache2/error.log or /var/log/httpd/error_log for errors, warnings, and diagnostic messages.

You can customize the log format using the LogFormat directive:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/log/apache2/access.log combined

Monitoring solutions like GoAccess, AWStats, or Elastic Stack can parse and visualize these logs, revealing traffic volumes, response codes, and performance bottlenecks.

Performance Tuning

MPM Settings

For the worker or event MPM, you might configure:

<IfModule mpm_worker_module>
    StartServers           2
    MinSpareThreads       25
    MaxSpareThreads       75
    ThreadLimit           64
    ThreadsPerChild       25
    MaxRequestWorkers     150
    MaxConnectionsPerChild 0
</IfModule>

The MaxRequestWorkers sets the total threads available. Adjust these for your application’s concurrency needs.

KeepAlive

Keep-alive allows multiple requests over a single TCP connection, reducing overhead. You can tweak:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Compression

Use mod_deflate to compress text-based responses:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
</IfModule>

Caching Headers and mod_expires

Set caching headers for static content:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 7 days"
    ExpiresByType application/javascript "access plus 7 days"
    ExpiresByType image/png "access plus 30 days"
</IfModule>

Security Hardening

  1. Disable Unused Modules: Turn off modules you don’t need (e.g., mod_autoindex if you don’t want directory listings).
  2. Hide Apache Version: Set ServerTokens Prod and ServerSignature Off to not reveal internal version details.
  3. Use Strong TLS Ciphers: Adjust SSLCipherSuite and SSLProtocol to avoid outdated cryptography.
  4. Restrict .htaccess: If possible, manage config at the server or virtual host level instead of allowing arbitrary .htaccess overrides.
  5. WAF: Consider adding a Web Application Firewall module, like ModSecurity, to block malicious traffic.

Common Administrative Tasks

Starting and Stopping

Use your system’s service manager:

sudo systemctl start apache2   # Debian/Ubuntu
sudo systemctl enable apache2
 
sudo systemctl stop httpd      # Red Hat/CentOS

Reloading Configuration

To apply config changes without dropping active connections abruptly:

sudo systemctl reload apache2  # or httpd

Checking Configuration

Apache has a built-in config test:

apachectl configtest

or

httpd -t

It reports syntax errors and other issues before you reload or restart.

Example Architecture Diagram

         Internet
           |
   (Requests on Port 80/443)
           |
           v
+-------------------+      +-----------------------+
|   Apache          |      |   Additional Modules: |
| (HTTP/HTTPS)      |----->|   - mod_security      |
| [VirtualHosts]    |      |   - mod_rewrite       |
| [mod_proxy, etc.] |      |   - mod_ssl           |
+---------+---------+      +-----------------------+
          |  Reverse Proxy or Localhost
          | for dynamic web apps
          v
 +--------------------+ 
 |   Backend Service  |   (PHP-FPM, Tomcat, Python WSGI, etc.)
 +--------------------+
          |
          v
  [Database, Other APIs]

In this diagram, Apache listens on ports 80 or 443. Static files are served directly, while dynamic requests are routed to backend services (PHP-FPM, Tomcat, etc.) or proxied to external APIs.