Apache logoApachev2.4INTERMEDIATE

Apache

Apache cheat sheet for virtual hosts, .htaccess rules, mod_rewrite, SSL setup, modules, and performance tuning with config examples.

10 min read
apachehttpdweb-serverhtaccessvirtual-hostsmodulesrewritessl

Sign in to mark items as known and track your progress.

Sign in

Installation & Basic Commands

Installing and managing Apache

Installation

Installing Apache on different platforms

bash
# Ubuntu/Debian
sudo apt update
sudo apt install apache2

# CentOS/RHEL/Fedora
sudo yum install httpd

# macOS with Homebrew
brew install httpd

# Check version
apache2 -v  # Debian/Ubuntu
httpd -v    # CentOS/RHEL
🌐 Most widely used web server
📦 Available as apache2 or httpd package
🔧 Highly modular and extensible
⚡ Config at /etc/apache2/ or /etc/httpd/

Commands & Configuration

Service commands, config testing, and configuration file locations

bash
# Start / stop / restart
sudo systemctl start apache2
sudo systemctl restart apache2
sudo systemctl reload apache2    # Graceful reload (no downtime)

# Test configuration before applying
sudo apachectl configtest        # Syntax OK or error details

# Check loaded modules
apachectl -M
💡 Always run apachectl configtest before restarting — catches syntax errors without downtime
⚡ Use reload instead of restart for zero-downtime config changes in production
📌 Debian uses a2ensite/a2dissite; RHEL puts everything in /etc/httpd/conf.d/
🟢 apachectl -S shows which virtual hosts are active and what ports they listen on

Virtual Hosts

Configuring virtual hosts for multiple sites

Basic Virtual Host

Setting up a basic virtual host

apache
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com

    <Directory /var/www/example.com>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
🌐 Virtual hosts allow multiple sites on one server
📝 Each vhost needs unique ServerName
🔗 Enable with a2ensite command
⚡ Name-based is most common type

SSL/TLS Configuration

Configuring HTTPS with SSL certificates

apache
# Redirect HTTP to HTTPS (must be a sibling block - vhosts cannot nest)
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example.com

    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
</VirtualHost>
🔒 Always use HTTPS in production
📜 Let's Encrypt for free SSL certificates
⚡ Enable HTTP/2 for better performance
🔐 HSTS header enforces HTTPS

Reverse Proxy

Proxy requests to backend application servers with mod_proxy

Reverse Proxy & Load Balancing

Forward requests to Node.js, Python, or other backend servers

apacheconf
# Enable required modules
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests

# Basic reverse proxy
<VirtualHost *:80>
    ServerName app.example.com
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>
💡 ProxyPreserveHost On sends the original Host header to the backend — essential for virtual hosts
⚡ Use ProxyPass /path ! to exclude paths from proxying (serve static files directly)
📌 WebSocket proxying needs mod_proxy_wstunnel and RewriteRule for the Upgrade header
🟢 Load balancing with BalancerMember distributes traffic across multiple backend instances
proxyreverse-proxyload-balancing

.htaccess & URL Rewriting

Directory-level configuration and URL rewriting

.htaccess Basics

Common .htaccess configurations

apache
# Enable rewrite engine
RewriteEngine On

# Redirect to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Remove www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# Custom error pages
ErrorDocument 404 /404.html
ErrorDocument 500 /500.html
📁 .htaccess provides directory-level config
🔒 Requires AllowOverride All in vhost
⚡ Can impact performance if overused
🎯 Great for shared hosting environments

URL Rewriting

Advanced URL rewriting with mod_rewrite

apache
# Basic rewrite
RewriteEngine On
RewriteRule ^old-page$ /new-page [R=301,L]

# Dynamic rewrite
RewriteRule ^user/([0-9]+)$ /profile.php?id=$1 [L]

# WordPress permalinks
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
🔄 mod_rewrite is powerful but complex
📝 Test rules carefully with RewriteLog
🎯 Order matters - most specific first
⚡ Use RewriteCond for conditional rules

Redirects & Error Pages

Simple redirects with mod_alias and custom error pages

apacheconf
# Permanent redirect (301)
Redirect 301 /old-page https://example.com/new-page

# Custom error pages
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
💡 Use Redirect (mod_alias) for simple URL redirects — mod_rewrite is overkill for basic cases
⚡ 301 is permanent (cached by browsers, transfers SEO); 302 is temporary (not cached)
📌 Force HTTPS with RewriteCond %{HTTPS} off — the most common rewrite rule on the web
🟢 ErrorDocument paths are relative to DocumentRoot — create an /errors/ directory for custom pages
redirecterror-pageshttps

Logging

Configure access logs, error logs, and custom log formats

Access & Error Logs

Configure log files, formats, and rotation

apacheconf
# Error log
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn

# Access log with combined format
CustomLog ${APACHE_LOG_DIR}/access.log combined
💡 Use combined format for access logs — it includes Referer and User-Agent for analysis
⚡ Set LogLevel rewrite:trace3 to debug mod_rewrite rules — essential when rules don't work
📌 Use SetEnvIf to exclude health checks and bots from access logs — keeps logs clean
🟢 Pipe logs to rotatelogs for automatic rotation without logrotate config
loggingaccess-logerror-log

Security & Access Control

Securing your Apache server

Authentication & Access Control

Password-protect directories and restrict access by IP

apacheconf
# Password-protect a directory
<Directory /var/www/admin>
    AuthType Basic
    AuthName "Admin Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

# Create password file
# htpasswd -c /etc/apache2/.htpasswd admin
💡 htpasswd -c creates the file — omit -c when adding users to an existing file or it overwrites
⚡ Options -Indexes prevents directory listing — always disable this in production
📌 Block .env, .git, and backup files with FilesMatch — they should never be web-accessible
🟢 Combine Require valid-user + Require ip inside <RequireAll> for defense in depth
authhtpasswdaccess-control

Security Best Practices

Essential security configurations

apache
# Hide Apache version
ServerTokens Prod
ServerSignature Off

# Disable directory listing
Options -Indexes

# Prevent clickjacking
Header always append X-Frame-Options SAMEORIGIN

# Block access to sensitive files
<FilesMatch "^\.(htaccess|htpasswd|ini|log|sh)">
    Order allow,deny
    Deny from all
</FilesMatch>
🔒 Hide version info and disable directory listing
🛡️ Use security headers to prevent attacks
⚠️ Implement ModSecurity for WAF protection
🔐 Use fail2ban to block attackers

Headers & CORS

Set security headers and configure CORS with mod_headers

apacheconf
# Enable mod_headers
# sudo a2enmod headers

# Security headers
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set Strict-Transport-Security "max-age=31536000"
💡 ServerTokens Prod hides your Apache version from response headers — basic security hygiene
⚡ HSTS with preload tells browsers to ALWAYS use HTTPS — submit to hstspreload.org
📌 Never use Access-Control-Allow-Origin "*" with credentials — use specific origins instead
🟢 Use SetEnvIf to dynamically set CORS origin from a whitelist of allowed domains
headerscorssecurity

Modules & Performance

Apache modules and performance optimization

Essential Modules

Common Apache modules and their usage

bash
# Enable modules (Debian/Ubuntu)
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod deflate

# List loaded modules
apache2 -M

# Module configuration
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule ssl_module modules/mod_ssl.so
🔧 Apache has 100+ available modules
📦 Enable only needed modules for performance
⚡ mod_deflate saves bandwidth
🔒 mod_security adds WAF capabilities

Performance Tuning

Optimizing Apache for better performance

apache
# MPM configuration
<IfModule mpm_prefork_module>
    StartServers 5
    MinSpareServers 5
    MaxSpareServers 10
    MaxRequestWorkers 150
    MaxConnectionsPerChild 0
</IfModule>

# Enable caching
<IfModule mod_cache.c>
    CacheEnable disk /
    CacheRoot /var/cache/apache2/mod_cache_disk
</IfModule>

# KeepAlive settings
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
⚙️ Choose appropriate MPM for workload
🗜️ Enable compression for text content
💾 Use caching for static content
📊 Monitor with mod_status

Caching & Compression

Enable GZIP compression and browser caching for performance

apacheconf
# Enable compression (mod_deflate)
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/css
    AddOutputFilterByType DEFLATE application/javascript application/json
</IfModule>

# Browser caching (mod_expires)
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
</IfModule>
💡 GZIP compression reduces text-based response sizes by 60-80% — enable it on every server
⚡ Set "access plus 1 year" for static assets with fingerprinted filenames (style.a1b2c3.css)
📌 HTML should have Cache-Control: no-cache so users always get the latest content
🟢 Use immutable with long max-age for hashed/fingerprinted assets — browsers skip revalidation
cachingcompressiongzipperformance