Set up Apache HTTP Server as a reverse proxy with intelligent caching for microservices architectures. This tutorial covers mod_proxy, mod_cache configuration, cache policies, and monitoring for high-performance service delivery.
Prerequisites
- Root or sudo access
- Basic understanding of HTTP and web services
- Microservices running on different ports
What this solves
A reverse proxy with caching reduces load on backend microservices by serving cached responses for repeated requests. Apache's mod_proxy and mod_cache modules provide flexible routing, load balancing, and intelligent caching that can dramatically improve response times and reduce resource usage across your service architecture.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you have the latest security patches and package versions.
sudo apt update && sudo apt upgrade -y
sudo dnf update -y
Install Apache HTTP Server
Install Apache web server which includes the proxy and caching modules we need.
sudo apt install -y apache2 apache2-utils
sudo dnf install -y httpd httpd-tools
Enable required Apache modules
Enable the proxy, cache, and related modules needed for reverse proxy functionality with caching.
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod headers
sudo a2enmod rewrite
# Modules are loaded via LoadModule directives in configuration
</code><h2><code>We'll configure these in the next steps</code></h2></pre>
</div>
</div>
</div>
<div class="step">
### Create cache directory
<p>Create a dedicated directory for Apache to store cached content with proper permissions.</p>
<pre class="terminal"><code>sudo mkdir -p /var/cache/apache2/mod_cache_disk
sudo chown www-data:www-data /var/cache/apache2/mod_cache_disk
sudo chmod 755 /var/cache/apache2/mod_cache_disk
Configure main Apache settings
Configure the main Apache configuration with performance optimizations for proxy and caching workloads.
# Add these settings at the end of the file
# Performance tuning for proxy workloads
MaxRequestWorkers 400
ThreadsPerChild 25
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
# Proxy timeout settings
ProxyTimeout 300
ProxyPreserveHost On
# Security headers
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy strict-origin-when-cross-origin
# Add these settings at the end of the file
# Load required modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so
# Performance tuning for proxy workloads
MaxRequestWorkers 400
ThreadsPerChild 25
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
# Proxy timeout settings
ProxyTimeout 300
ProxyPreserveHost On
# Security headers
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy strict-origin-when-cross-origin
Create virtual host configuration
Create a virtual host that configures reverse proxy with caching for your microservices.
Create cache directory for Red Hat systems
On Red Hat-based systems, create the cache directory with SELinux context.
# Cache directory already created in previous step
sudo mkdir -p /var/cache/httpd/mod_cache_disk
sudo chown apache:apache /var/cache/httpd/mod_cache_disk
sudo chmod 755 /var/cache/httpd/mod_cache_disk
sudo setsebool -P httpd_can_network_connect 1
sudo semanage fcontext -a -t httpd_cache_t "/var/cache/httpd/mod_cache_disk(/.*)?" || true
sudo restorecon -R /var/cache/httpd/mod_cache_disk
Enable the virtual host
Enable the new virtual host configuration and disable the default site.
sudo a2ensite microservices-proxy.conf
sudo a2dissite 000-default.conf
# Configuration is automatically loaded from conf.d directory
Configure cache cleanup
Set up automatic cache cleanup to prevent disk space issues. Create a systemd timer to clean old cache files.
[Unit]
Description=Apache Cache Cleanup
After=network.target
[Service]
Type=oneshot
User=www-data
Group=www-data
ExecStart=/usr/bin/find /var/cache/apache2/mod_cache_disk -type f -mtime +7 -delete
ExecStart=/usr/bin/find /var/cache/apache2/mod_cache_disk -type d -empty -delete
[Unit]
Description=Run Apache Cache Cleanup Daily
Requires=apache-cache-cleanup.service
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now apache-cache-cleanup.timer
Test configuration and start Apache
Test the Apache configuration for syntax errors and start the service.
sudo apache2ctl configtest
sudo systemctl enable --now apache2
sudo systemctl status apache2
sudo httpd -t
sudo systemctl enable --now httpd
sudo systemctl status httpd
Configure firewall rules
Open HTTP and HTTPS ports in the firewall for web traffic.
sudo ufw allow 'Apache Full'
sudo ufw reload
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Configure cache policies and optimization
Advanced cache configuration
Fine-tune cache behavior with advanced policies for different types of content and API responses.
# Cache size limits and memory settings
CacheMaxFileSize 10000000
CacheMinFileSize 1
CacheReadSize 102400
CacheReadTime 3600
# Ignore certain headers that prevent caching
CacheIgnoreHeaders Set-Cookie
CacheIgnoreQueryString Off
CacheKeyBaseURL http://api.example.com
# Cache based on Accept-Encoding for compressed content
CacheStorePrivate On
CacheStoreNoStore Off
# Advanced cache policies
# Don't cache authentication endpoints
# Cache size limits and memory settings
CacheMaxFileSize 10000000
CacheMinFileSize 1
CacheReadSize 102400
CacheReadTime 3600
# Ignore certain headers that prevent caching
CacheIgnoreHeaders Set-Cookie
CacheIgnoreQueryString Off
CacheKeyBaseURL http://api.example.com
# Cache based on Accept-Encoding for compressed content
CacheStorePrivate On
CacheStoreNoStore Off
# Advanced cache policies
# Don't cache authentication endpoints
Enable cache optimization
Enable the cache optimization configuration and reload Apache.
sudo a2enconf cache-optimization
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo httpd -t
sudo systemctl reload httpd
Monitor and troubleshoot reverse proxy
Set up cache monitoring script
Create a monitoring script to track cache performance and hit rates.
#!/bin/bash
# Apache cache monitoring script
CACHE_DIR="/var/cache/apache2/mod_cache_disk"
LOG_FILE="/var/log/apache2/microservices_cache.log"
# Cache disk usage
echo "Cache Directory Usage:"
du -sh $CACHE_DIR
echo ""
# Cache files count
echo "Cache Files Count:"
find $CACHE_DIR -type f | wc -l
echo ""
# Recent cache statistics from logs
echo "Cache Hit/Miss Statistics (last 1000 requests):"
if [ -f "$LOG_FILE" ]; then
tail -1000 $LOG_FILE | awk '{
if ($NF ~ /HIT/) hits++;
else if ($NF ~ /MISS/) misses++;
total++
} END {
if (total > 0) {
hit_rate = (hits/total)*100;
printf "Hits: %d (%.1f%%)\n", hits, hit_rate;
printf "Misses: %d (%.1f%%)\n", misses, 100-hit_rate;
printf "Total: %d\n", total;
} else {
print "No cache data found in logs";
}
}'
else
echo "Cache log file not found"
fi
# Top requested URLs being cached
echo ""
echo "Top 10 Cached URLs:"
if [ -f "$LOG_FILE" ]; then
tail -1000 $LOG_FILE | awk '{print $7}' | sort | uniq -c | sort -nr | head -10
fi
sudo chmod +x /usr/local/bin/apache-cache-stats.sh
Configure l
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Apache Reverse Proxy with Caching Setup Script
# Configures Apache with mod_proxy and mod_cache for microservices
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Cleanup function for error handling
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Check logs above for details.${NC}"
exit 1
}
trap cleanup ERR
# Usage message
usage() {
echo "Usage: $0 <domain_name> [backend_service_1:port] [backend_service_2:port] ..."
echo "Example: $0 api.example.com localhost:3000 localhost:3001"
exit 1
}
# Check arguments
if [ $# -lt 2 ]; then
usage
fi
DOMAIN_NAME="$1"
shift
BACKEND_SERVICES=("$@")
# Check if running as root or with sudo
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}[ERROR] This script must be run as root or with sudo${NC}"
exit 1
fi
# Auto-detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
APACHE_SERVICE="apache2"
APACHE_CONFIG_DIR="/etc/apache2"
SITES_DIR="/etc/apache2/sites-available"
SITES_ENABLED="/etc/apache2/sites-enabled"
APACHE_USER="www-data"
USE_A2ENMOD=true
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
APACHE_SERVICE="httpd"
APACHE_CONFIG_DIR="/etc/httpd"
SITES_DIR="/etc/httpd/conf.d"
APACHE_USER="apache"
USE_A2ENMOD=false
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
APACHE_SERVICE="httpd"
APACHE_CONFIG_DIR="/etc/httpd"
SITES_DIR="/etc/httpd/conf.d"
APACHE_USER="apache"
USE_A2ENMOD=false
;;
*)
echo -e "${RED}[ERROR] Unsupported distribution: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}[ERROR] Cannot detect distribution${NC}"
exit 1
fi
echo -e "${GREEN}[1/8] Updating system packages...${NC}"
$PKG_UPDATE
echo -e "${GREEN}[2/8] Installing Apache HTTP Server...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL apache2 apache2-utils
else
$PKG_INSTALL httpd httpd-tools
fi
echo -e "${GREEN}[3/8] Enabling required Apache modules...${NC}"
if [ "$USE_A2ENMOD" = true ]; then
# Debian/Ubuntu systems
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod lbmethod_byrequests
a2enmod cache
a2enmod cache_disk
a2enmod headers
a2enmod rewrite
else
# RHEL-based systems - modules are loaded via configuration
MAIN_CONFIG="${APACHE_CONFIG_DIR}/conf/httpd.conf"
# Check if modules are already loaded to avoid duplicates
if ! grep -q "LoadModule proxy_module" "$MAIN_CONFIG"; then
cat >> "$MAIN_CONFIG" << 'EOF'
# Proxy and Cache modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so
EOF
fi
fi
echo -e "${GREEN}[4/8] Creating cache directory...${NC}"
CACHE_DIR="/var/cache/${APACHE_SERVICE}/mod_cache_disk"
mkdir -p "$CACHE_DIR"
chown "$APACHE_USER:$APACHE_USER" "$CACHE_DIR"
chmod 755 "$CACHE_DIR"
echo -e "${GREEN}[5/8] Configuring Apache performance settings...${NC}"
MAIN_CONFIG_FILE="${APACHE_CONFIG_DIR}/apache2.conf"
if [ "$PKG_MGR" != "apt" ]; then
MAIN_CONFIG_FILE="${APACHE_CONFIG_DIR}/conf/httpd.conf"
fi
if ! grep -q "MaxRequestWorkers 400" "$MAIN_CONFIG_FILE"; then
cat >> "$MAIN_CONFIG_FILE" << 'EOF'
# Performance tuning for proxy workloads
MaxRequestWorkers 400
ThreadsPerChild 25
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
# Proxy timeout settings
ProxyTimeout 300
ProxyPreserveHost On
# Security headers
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy strict-origin-when-cross-origin
EOF
fi
echo -e "${GREEN}[6/8] Creating virtual host configuration...${NC}"
# Build proxy balancer configuration
BALANCER_CONFIG=""
BALANCER_MEMBERS=""
for i in "${!BACKEND_SERVICES[@]}"; do
service="${BACKEND_SERVICES[$i]}"
BALANCER_MEMBERS+=" BalancerMember http://${service}\\n"
done
# Create virtual host configuration
VHOST_CONFIG="${SITES_DIR}/${DOMAIN_NAME}.conf"
cat > "$VHOST_CONFIG" << EOF
<VirtualHost *:80>
ServerName ${DOMAIN_NAME}
DocumentRoot /var/www/html
# Enable caching
CacheEnable disk /
CacheRoot ${CACHE_DIR}
CacheDirLevels 2
CacheDirLength 1
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheMinExpire 60
CacheDetailHeader on
CacheHeader on
# Cache policies for different content types
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$">
CacheDefaultExpire 604800
ExpiresActive On
ExpiresDefault "access plus 1 week"
Header set Cache-Control "public, max-age=604800"
</LocationMatch>
<LocationMatch "\.(json|xml)$">
CacheDefaultExpire 300
ExpiresActive On
ExpiresDefault "access plus 5 minutes"
Header set Cache-Control "public, max-age=300"
</LocationMatch>
# Proxy balancer configuration
ProxyPreserveHost On
ProxyRequests Off
<Proxy balancer://microservices>
$(echo -e "$BALANCER_MEMBERS")
ProxySet lbmethod=byrequests
</Proxy>
# Route all requests to the balancer
ProxyPassMatch ^/(.*)$ balancer://microservices/\$1
ProxyPassReverse / balancer://microservices/
# Balancer manager (restrict access in production)
<Location "/balancer-manager">
SetHandler balancer-manager
Require local
</Location>
ProxyPass /balancer-manager !
# Logging
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN_NAME}_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN_NAME}_access.log combined
</VirtualHost>
EOF
chmod 644 "$VHOST_CONFIG"
echo -e "${GREEN}[7/8] Enabling virtual host and starting Apache...${NC}"
if [ "$USE_A2ENMOD" = true ]; then
# Enable site on Debian/Ubuntu
a2ensite "${DOMAIN_NAME}.conf"
# Disable default site if it exists
if [ -f "/etc/apache2/sites-enabled/000-default.conf" ]; then
a2dissite 000-default
fi
fi
# Test Apache configuration
if "${APACHE_SERVICE}" -t; then
echo -e "${YELLOW}Apache configuration test passed${NC}"
else
echo -e "${RED}[ERROR] Apache configuration test failed${NC}"
exit 1
fi
# Start and enable Apache service
systemctl enable "$APACHE_SERVICE"
systemctl restart "$APACHE_SERVICE"
# Configure firewall if present
if command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then
echo -e "${YELLOW}Configuring firewalld...${NC}"
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
elif command -v ufw &> /dev/null; then
echo -e "${YELLOW}Configuring ufw...${NC}"
ufw --force enable
ufw allow 80/tcp
fi
echo -e "${GREEN}[8/8] Verifying installation...${NC}"
# Check if Apache is running
if systemctl is-active --quiet "$APACHE_SERVICE"; then
echo -e "${GREEN}✓ Apache is running${NC}"
else
echo -e "${RED}✗ Apache is not running${NC}"
exit 1
fi
# Check if cache directory exists and has correct permissions
if [ -d "$CACHE_DIR" ] && [ "$(stat -c %U:%G "$CACHE_DIR")" = "${APACHE_USER}:${APACHE_USER}" ]; then
echo -e "${GREEN}✓ Cache directory configured correctly${NC}"
else
echo -e "${RED}✗ Cache directory configuration failed${NC}"
exit 1
fi
# Check if virtual host file exists
if [ -f "$VHOST_CONFIG" ]; then
echo -e "${GREEN}✓ Virtual host configuration created${NC}"
else
echo -e "${RED}✗ Virtual host configuration missing${NC}"
exit 1
fi
echo -e "${GREEN}[SUCCESS] Apache reverse proxy with caching has been configured successfully!${NC}"
echo -e "${YELLOW}Configuration details:${NC}"
echo " - Domain: ${DOMAIN_NAME}"
echo " - Backend services: ${BACKEND_SERVICES[*]}"
echo " - Cache directory: ${CACHE_DIR}"
echo " - Virtual host config: ${VHOST_CONFIG}"
echo " - Balancer manager: http://${DOMAIN_NAME}/balancer-manager"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Update your DNS to point ${DOMAIN_NAME} to this server"
echo "2. Test the setup: curl -H 'Host: ${DOMAIN_NAME}' http://localhost/"
echo "3. Monitor logs: tail -f ${APACHE_LOG_DIR}/${DOMAIN_NAME}_access.log"
echo "4. Consider setting up SSL/TLS certificates for production use"
Review the script before running. Execute with: bash install.sh