Apache Performance & Security
A default Apache install is not tuned for production. Enabling caching, tuning KeepAlive, hiding server info, and adding security headers are the essential steps before going live.
KeepAlive & Connection Tuning
# In apache2.conf or vhost config
# KeepAlive — reuse TCP connections for multiple requests
KeepAlive On
MaxKeepAliveRequests 100 # Max requests per connection (0 = unlimited)
KeepAliveTimeout 5 # Seconds to wait for next request (lower = more efficient)
# Timeout settings
Timeout 60 # Request timeout in seconds
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
# Limit request sizes (protect against large body attacks)
LimitRequestBody 10485760 # 10 MB max request body
# mod_cache with mod_cache_disk
sudo a2enmod cache cache_disk
<IfModule mod_cache_disk.c>
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_cache_disk
CacheDirLevels 2
CacheDirLength 1
CacheDefaultExpire 3600 # 1 hour default
CacheMaxExpire 86400 # 24 hour max
CacheIgnoreHeaders Set-Cookie
</IfModule>Security Hardening
# Hide server version and OS info
ServerTokens Prod # Show only "Apache" not version
ServerSignature Off # Remove version from error pages
# Disable directory listing globally
<Directory />
Options -Indexes
AllowOverride None
Require all denied # Deny everything by default, open up explicitly
</Directory>
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Block access to hidden files (.git, .env, .htpasswd)
<FilesMatch "^.">
Require all denied
</FilesMatch>
# Block access to sensitive extensions
<FilesMatch ".(sql|bak|config|log|sh)$">
Require all denied
</FilesMatch>
# Basic auth with .htpasswd
sudo apt install apache2-utils
htpasswd -c /etc/apache2/.htpasswd admin # Create file and add user
htpasswd /etc/apache2/.htpasswd editor # Add another user
<Directory /var/www/html/private>
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
# mod_ratelimit — limit bandwidth per connection
sudo a2enmod ratelimit
<Location /downloads>
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 400 # 400 KB/s per connection
</Location>Security Headers & mod_security
# Add security headers (in vhost or .htaccess)
sudo a2enmod headers
<IfModule mod_headers.c>
# Prevent clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Prevent MIME type sniffing
Header always set X-Content-Type-Options "nosniff"
# XSS protection (legacy browsers)
Header always set X-XSS-Protection "1; mode=block"
# HSTS — force HTTPS for 2 years including subdomains
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# Content Security Policy
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
# Referrer policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# Install ModSecurity WAF
sudo apt install libapache2-mod-security2
sudo a2enmod security2
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# Change DetectionOnly to On to enforce rules
sudo sed -i "s/SecRuleEngine DetectionOnly/SecRuleEngine On/" /etc/modsecurity/modsecurity.conf
# Test config and reload
sudo apachectl configtest && sudo systemctl reload apache2
# Check for misconfigurations causing 403/500 errors
sudo tail -50 /var/log/apache2/error.log
sudo journalctl -u apache2 --since "5 minutes ago"Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free