Skip to content

Apache

Chapter 66: Apache HTTP Server - Deep Dive

Section titled “Chapter 66: Apache HTTP Server - Deep Dive”

Mastering Apache for Production Web Serving

Section titled “Mastering Apache for Production Web Serving”

Apache remains a critical component in many enterprise web infrastructures. As a DevOps/SRE, you’ll often need to configure, optimize, troubleshoot, and secure Apache servers. Understanding Apache architecture helps with incident response, capacity planning, and performance tuning.

┌─────────────────────────────────────────────────────────────────────────────┐
│ APACHE IN DEVOPS/SRE LIFECYCLE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CONFIGURATION MANAGEMENT │ │
│ │ │ │
│ │ Ansible/Terraform ──► httpd.conf ──► Version control │ │
│ │ │ │
│ │ # Ensure consistent configs across all web servers │ │
│ │ - name: Configure Apache │ │
│ │ template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ MONITORING & ALERTING │ │
│ │ │ │
│ │ Apache Status ──► mod_status ──► Prometheus/Grafana │ │
│ │ │ │
│ │ Key metrics: Requests/sec, Workers busy, Queue length │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ INCIDENT RESPONSE │ │
│ │ │ │
│ │ "Site down" ──► Check Apache status ──► Review error logs │ │
│ │ │ │
│ │ Common issues: MaxClients reached, SSL cert expired, config error│ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Real-world DevOps scenarios:

  • Load balancer failover: Apache as backend behind AWS ALB, handling SSL termination
  • Reverse proxy: Apache mod_proxy routing traffic to application servers
  • Static content delivery: Optimizing Apache for serving React/Angular builds
  • API gateway: Using Apache as lightweight API gateway with mod_rewrite

The Apache HTTP Server (httpd) is the world’s most widely used web server, known for its flexibility, power, and extensive module support. It follows a modular architecture where functionality is added through Dynamic Shared Objects (DSOs).

Apache Architecture
+------------------------------------------------------------------+
| |
| Apache HTTP Server |
| +-------------------------------------------------------------+ |
| | MPM (Multi-Processing Module) | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | prefork | | worker | | event | | kqueue | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | | |
| +------------------------------+----------------------------------+ |
| | |
| +---------------------------+-----------------------------------+ |
| | Core Modules | |
| | +--------+ +--------+ +--------+ +--------+ +--------+ | |
| | | mod_php| |mod_ssl | |mod_rewrite| |mod_proxy| |mod_log| | |
| | +--------+ +--------+ +--------+ +--------+ +--------+ | |
| +-------------------------------------------------------------+ |
| | |
| +---------------------------+-----------------------------------+ |
| | Configuration Files | |
| | +-----------+ +---------------+ +---------------+ | |
| | | httpd.conf| | conf.d/*.conf| | sites-enabled/| | |
| | +-----------+ +---------------+ +---------------+ | |
| +-------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Apache MPM Comparison
+------------------------------------------------------------------+
| |
| prefork (Default on many distributions) |
| +----------------------------------------------------------+ |
| | - Pre-forks child processes before requests | |
| | - Each process handles one connection | |
| | - Best for: Non-thread-safe libraries (PHP) | |
| | - Memory: Higher (each process has own memory) | |
| | - Stability: Excellent (process isolation) | |
| +----------------------------------------------------------+ |
| |
| worker |
| +----------------------------------------------------------+ |
| | - Hybrid multi-process, multi-threaded | |
| | - Each process has multiple threads | |
| | - Better memory efficiency than prefork | |
| | - Best for: High concurrency | |
| +----------------------------------------------------------+ |
| |
| event (Default on modern Apache) |
| +----------------------------------------------------------+ |
| | - Based on worker, but optimizes keep-alive | |
| | - Dedicated thread handles keep-alive connections | |
| | - Best for: High traffic with persistent connections | |
| | - Recommended for modern workloads | |
| +----------------------------------------------------------+ |
| |
| Key Differences: |
| +----------------------------------------------------------+ |
| | MPM | Threading | Memory | Stability | Use Case | |
| | ------------|-----------|---------|-----------|------------| |
| | prefork | No | Higher | Best | PHP/mod_php | |
| | worker | Yes | Lower | Good | Mixed | |
| | event | Yes | Lowest | Good | High traffic| |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

66.2 Apache Installation and Configuration

Section titled “66.2 Apache Installation and Configuration”
Terminal window
# =============================================================================
# ARCH LINUX
# =============================================================================
# Install Apache
sudo pacman -S apache
# Install with PHP (if needed)
sudo pacman -S php php-apache
# Enable required modules
sudo systemctl enable --now httpd
# =============================================================================
# UBUNTU/DEBIAN
# =============================================================================
# Install Apache
sudo apt update
sudo apt install apache2
# Install modules
sudo a2enmod ssl rewrite headers proxy proxy_fcgi
# Install PHP with FPM
sudo apt install php-fpm
sudo a2enmod proxy_fcgi setenvif
# Enable required sites
sudo a2ensite default-ssl
sudo a2enmod php8.1-fpm
# Start Apache
sudo systemctl enable --now apache2
# =============================================================================
# RHEL/CENTOS
# =============================================================================
# Install Apache
sudo dnf install httpd
# Install PHP
sudo dnf install php php-fpm
# Enable and start
sudo systemctl enable --now httpd
# Configure firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Terminal window
# /etc/httpd/conf/httpd.conf (RHEL/CentOS)
# /etc/apache2/apache2.conf (Debian/Ubuntu)
ServerRoot "/etc/httpd"
Listen 80
Listen 443
# Load essential modules
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
# User/Group (RHEL)
User apache
Group apache
# Server settings
ServerAdmin admin@example.com
ServerName server.example.com:80
# Document root
DocumentRoot "/var/www/html"
# Directory permissions
<Directory />
AllowOverride none
Require all denied
</Directory>
<Directory "/var/www">
AllowOverride None
Require all granted
</Directory>
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Default index
DirectoryIndex index.html
# Logging
ErrorLog "logs/error_log"
LogLevel warn
# MIME types
TypesConfig /etc/mime.types
# Include additional configs
IncludeOptional conf.d/*.conf

Virtual Host Types
+------------------------------------------------------------------+
| |
| Name-Based Virtual Hosting |
| +----------------------------------------------------------+ |
| | - Multiple websites on single IP address | |
| | - Based on Host header in request | |
| | - Most common configuration | |
| | - Requires DNS to point to same IP | |
| | | |
| | Example: | |
| | site1.example.com -> 192.168.1.10 | |
| | site2.example.com -> 192.168.1.10 | |
| +----------------------------------------------------------+ |
| |
| IP-Based Virtual Hosting |
| +----------------------------------------------------------+ |
| | - Each website has unique IP address | |
| | - Requires multiple IP addresses | |
| | - Used when SSL certificates need dedicated IPs | |
| | - Older method, less common today | |
| +----------------------------------------------------------+ |
| |
| Port-Based Virtual Hosting |
| +----------------------------------------------------------+ |
| | - Different websites on different ports | |
| | - Example: :80 and :8080 | |
| | - Less common for production | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
/etc/apache2/sites-available/site1.conf
# Name-based virtual host for HTTP
<VirtualHost *:80>
ServerName site1.example.com
ServerAlias www.site1.example.com
ServerAdmin admin@site1.example.com
DocumentRoot /var/www/site1/public_html
# Logging
ErrorLog ${APACHE_LOG_DIR}/site1-error.log
CustomLog ${APACHE_LOG_DIR}/site1-access.log combined
# Directory permissions
<Directory /var/www/site1/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Security headers
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
</IfModule>
# Redirect to HTTPS
Redirect permanent / https://site1.example.com/
</VirtualHost>
# HTTPS virtual host
<VirtualHost *:443>
ServerName site1.example.com
ServerAlias www.site1.example.com
ServerAdmin admin@site1.example.com
DocumentRoot /var/www/site1/public_html
# SSL configuration
SSLEngine on
SSLCertificateFile /etc/ssl/certs/site1.crt
SSLCertificateKeyFile /etc/ssl/private/site1.key
SSLCertificateChainFile /etc/ssl/certs/site1-ca.crt
# SSL settings
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
<Directory /var/www/site1/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Logging
ErrorLog ${APACHE_LOG_DIR}/site1-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/site1-ssl-access.log combined
</VirtualHost>

Apache Modules Overview
+------------------------------------------------------------------+
| |
| Core Modules (Built-in) |
| +----------------------------------------------------------+ |
| | mod_core - Core functionality | |
| | mod_log_config - Logging | |
| | mod_mime - Content type detection | |
| | mod_dir - Directory index | |
| | mod_alias - URL redirection | |
| | mod_rewrite - URL rewriting | |
| +----------------------------------------------------------+ |
| |
| Common Modules (Enable with a2enmod) |
| +----------------------------------------------------------+ |
| | mod_ssl - SSL/TLS support | |
| | mod_php - PHP integration | |
| | mod_proxy - Proxy functionality | |
| | mod_proxy_fcgi - FastCGI proxy | |
| | mod_headers - HTTP headers manipulation | |
| | mod_expires - Cache control headers | |
| | mod_deflate - Compression (gzip) | |
| | mod_cache - Caching | |
| | mod_remoteip - IP anonymization | |
| +----------------------------------------------------------+ |
| |
| Security Modules |
| +----------------------------------------------------------+ |
| | mod_security - Web Application Firewall | |
| | mod_authz_core - Core authorization | |
| | mod_auth_basic - Basic authentication | |
| | mod_auth_digest - Digest authentication | |
| | mod_authn_file - File-based authentication | |
| | mod_authz_groupfile - Group authorization | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# List enabled modules (Debian/Ubuntu)
apache2ctl -M
a2query -m
# Enable module
sudo a2enmod ssl
sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod proxy
sudo a2enmod proxy_fcgi
# Disable module
sudo a2dismod ssl
sudo a2dismod php
# Check module status
apachectl -t -D DUMP_MODULES

# SSL Virtual Host Configuration
<VirtualHost *:443>
ServerName example.com
# Enable SSL
SSLEngine on
# Certificate files
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
# Modern SSL configuration
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder on
# Ciphers (Mozilla Intermediate)
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# HSTS (HTTP Strict Transport Security)
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
SSLStaplingStandardCacheTimeout 3600
SSLStaplingErrorCacheTimeout 3600
</VirtualHost>
Terminal window
# Self-signed certificate (for testing)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt
# Generate CSR for CA-signed certificate
sudo openssl req -new -newkey rsa:2048 -nodes \
-keyout server.key -out server.csr
# View certificate details
openssl x509 -in server.crt -text -noout
openssl x509 -in server.crt -text -noout -certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_extensions,no_sigdump,no_aux
# Test SSL configuration
openssl s_client -connect example.com:443 -servername example.com

/etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
# StartServers: Number of child processes created at startup
StartServers 4
# MinSpareServers: Minimum number of idle child processes
MinSpareServers 10
# MaxSpareServers: Maximum number of idle child processes
MaxSpareServers 20
# ServerLimit: Maximum configured value for MaxRequestWorkers
ServerLimit 25
# MaxRequestWorkers: Maximum number of connections
MaxRequestWorkers 25
# MaxConnectionsPerChild: Connections per child process
MaxConnectionsPerChild 0 # 0 = unlimited
</IfModule>
# For high-traffic servers:
<IfModule mpm_event_module>
StartServers 8
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
# Enable compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
# Compression level
DeflateCompressionLevel 6
# Don't compress images
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
</IfModule>
# Browser caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
# ETag
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None

# Hide Apache version
ServerTokens Prod
ServerSignature Off
# Disable directory listing
<Directory />
Options -Indexes -FollowSymLinks
AllowOverride None
Require all denied
</Directory>
# Protect sensitive files
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
<FilesMatch "\.(env|log|conf|ini|yml|yaml|md|gitignore|dockerignore)$">
Require all denied
</FilesMatch>
# Prevent clickjacking
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
# Rate limiting (if mod_ratelimit is enabled)
<IfModule mod_ratelimit.c>
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 4096
</IfModule>
# Limit request size
<Directory "/var/www/upload">
LimitRequestBody 10485760 # 10MB
</Directory>
# Timeouts
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Terminal window
# Test configuration
sudo apachectl configtest
sudo apachectl -t
sudo apache2ctl configtest
# Syntax check
apachectl -t -D DUMP_CONFIG
# Start/Stop/Restart
sudo systemctl start apache2
sudo systemctl stop apache2
sudo systemctl restart apache2
sudo systemctl reload apache2
# Graceful restart (reload without downtime)
sudo apachectl graceful
sudo systemctl reload apache2
# Check status
sudo systemctl status apache2
# List virtual hosts
apache2ctl -S
apachectl -t -D VHOSTS
# Show compiled-in modules
apachectl -l
# Show loaded modules
apache2ctl -M

Important

  1. MPM: Know the difference between prefork, worker, and event
  2. Virtual Hosts: Understand name-based vs IP-based
  3. Modules: Enable modules with a2enmod (Debian)
  4. SSL: Use modern protocols (TLS 1.2+) and ciphers
  5. Security: Hide version, set security headers
  6. Performance: Enable compression, configure caching
  7. Configuration: Always test with apachectl configtest
  8. Logging: Know where logs are stored
  9. .htaccess: Understand AllowOverride directives
  10. Rewrite: Use mod_rewrite for URL manipulation

1. Not Testing Configuration Before Reload

Section titled “1. Not Testing Configuration Before Reload”

❌ WRONG: Reloading Apache with syntax errors

Terminal window
# Don't do this!
service httpd reload # If config has errors, service crashes

✅ CORRECT: Always test first

Terminal window
# Test configuration before reloading
apachectl configtest
# Output: Syntax OK
# Only then reload
systemctl reload httpd

❌ WRONG: Using prefork for PHP with threads

# Wrong for PHP-FPM workloads - prefork creates multiple processes
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>

✅ CORRECT: Use event MPM for PHP-FPM

# Better for PHP-FPM - event MPM with threads
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxRequestWorkers 150
MaxSpareThreads 75
ThreadsPerChild 25
</IfModule>

❌ WRONG: Exposing server version

# Default exposes: Server: Apache/2.4.41 (Ubuntu) PHP/7.4
ServerTokens OS
ServerSignature On

✅ CORRECT: Hide server information

# Production security
ServerTokens Prod
ServerSignature Off
ServerTokens Min

❌ WRONG: New connection for each request

# Default often disabled
KeepAlive Off

✅ CORRECT: Enable for better performance

# Enable persistent connections
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

❌ WREXT: Allowing per-directory config overrides

# Performance hit - Apache checks .htaccess in every directory
AllowOverride All

✅ CORRECT: Disable where not needed

# Better performance - no .htaccess lookup
AllowOverride None
# Or only where needed
AllowOverride FileInfo

In this chapter, you learned:

  • ✅ Apache architecture and MPM comparison
  • ✅ Installation across distributions
  • ✅ Virtual host configuration
  • ✅ Module management
  • ✅ SSL/TLS configuration
  • ✅ Performance tuning
  • ✅ Security best practices
  • ✅ Common management commands

Chapter 67: Nginx Web Server


Last Updated: February 2026