Enable HTTP/2 protocol in Apache with SSL/TLS encryption, implement advanced performance optimization settings including compression and caching, and configure modern security headers for production deployments.
Prerequisites
- Root or sudo access
- Basic Apache knowledge
- SSL certificate or ability to generate one
What this solves
HTTP/2 provides significant performance improvements over HTTP/1.1 through multiplexing, server push, and header compression. This tutorial configures Apache with HTTP/2 support, SSL/TLS encryption, performance optimization settings, and modern security headers for production environments.
Step-by-step configuration
Update system packages and install Apache
Start by updating your system and installing Apache with SSL support.
sudo apt update && sudo apt upgrade -y
sudo apt install -y apache2 apache2-utils ssl-cert
sudo dnf update -y
sudo dnf install -y httpd mod_ssl openssl
Enable HTTP/2 and SSL modules
Enable the required modules for HTTP/2, SSL, and performance optimization.
sudo a2enmod ssl
sudo a2enmod http2
sudo a2enmod rewrite
sudo a2enmod deflate
sudo a2enmod expires
sudo a2enmod headers
sudo a2enmod cache
sudo a2enmod cache_disk
sudo sed -i 's/#LoadModule ssl_module/LoadModule ssl_module/' /etc/httpd/conf.modules.d/00-ssl.conf
echo "LoadModule http2_module modules/mod_http2.so" | sudo tee /etc/httpd/conf.modules.d/10-http2.conf
echo "LoadModule rewrite_module modules/mod_rewrite.so" | sudo tee -a /etc/httpd/conf.modules.d/00-base.conf
Generate SSL certificate
Create a self-signed SSL certificate for testing. Replace with a proper certificate from Let's Encrypt or your CA in production.
sudo mkdir -p /etc/ssl/private
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"
Configure Apache main settings
Set up the main Apache configuration with HTTP/2 support and performance optimizations.
# HTTP/2 Configuration
Protocols h2 h2c http/1.1
H2Direct on
H2Upgrade on
H2StreamMaxMemSize 512000
H2MaxSessionStreams 100
H2InitialWindowSize 65536
H2MaxWorkerIdleSeconds 600
# Performance Optimizations
ServerTokens Prod
ServerSignature Off
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
Timeout 300
# Compression Settings
DeflateCompressionLevel 6
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|webp|ico|svg)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
# HTTP/2 Configuration
Protocols h2 h2c http/1.1
H2Direct on
H2Upgrade on
H2StreamMaxMemSize 512000
H2MaxSessionStreams 100
H2InitialWindowSize 65536
H2MaxWorkerIdleSeconds 600
# Performance Optimizations
ServerTokens Prod
ServerSignature Off
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
Timeout 300
# Compression Settings
DeflateCompressionLevel 6
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|webp|ico|svg)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
Configure SSL virtual host with HTTP/2
Create a virtual host configuration with SSL, HTTP/2, and security headers.
Configure HTTP to HTTPS redirect
Set up automatic redirection from HTTP to HTTPS for security.
Configure MPM for HTTP/2 optimization
Tune the Multi-Processing Module settings for optimal HTTP/2 performance.
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
# Comment out prefork module
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
# Enable event module
LoadModule mpm_event_module modules/mod_mpm_event.so
Enable sites and restart Apache
Enable the configurations and restart Apache to apply changes.
sudo a2enconf http2
sudo a2ensite https-example
sudo a2ensite http-redirect
sudo apache2ctl configtest
sudo systemctl restart apache2
sudo systemctl enable apache2
sudo httpd -t
sudo systemctl restart httpd
sudo systemctl enable httpd
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Create test content
Create sample content to test HTTP/2 functionality and performance features.
sudo mkdir -p /var/www/html/css /var/www/html/js
<h1>Apache HTTP/2 Configuration Test</h1>
<p>This page tests HTTP/2, compression, and security headers.</p>
<div></div>
body {
font-family: Arial, sans-serif;
margin: 40px;
background-color: #f4f4f4;
}
h1 {
color: #333;
border-bottom: 2px solid #007acc;
padding-bottom: 10px;
}
#protocol-info {
background: #007acc;
color: white;
padding: 20px;
border-radius: 5px;
margin-top: 20px;
}
document.addEventListener('DOMContentLoaded', function() {
const protocolInfo = document.getElementById('protocol-info');
const protocol = window.location.protocol;
const host = window.location.host;
protocolInfo.innerHTML = `
<h3>Connection Information</h3>
<p><strong>Protocol:</strong> ${protocol}</p>
<p><strong>Host:</strong> ${host}</p>
<p><strong>User Agent:</strong> ${navigator.userAgent}</p>
`;
});
Set correct file permissions
Set proper ownership and permissions for web files. Never use chmod 777 as it gives unnecessary access to all users.
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
sudo chown -R apache:apache /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
Verify your setup
Test your HTTP/2 configuration and performance optimizations.
# Check Apache status and configuration
sudo systemctl status apache2 # or httpd on RHEL-based
sudo apache2ctl configtest # or httpd -t on RHEL-based
# Test HTTP/2 support
curl -I --http2 -k https://example.com/
# Check enabled modules
apache2ctl -M | grep -E '(http2|ssl|deflate|headers|expires)' # Ubuntu/Debian
httpd -M | grep -E '(http2|ssl|deflate|headers|expires)' # RHEL-based
# Test compression
curl -H "Accept-Encoding: gzip,deflate" -k https://example.com/ -v
# Check SSL configuration
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text | grep -A2 "Subject:"
# Monitor Apache processes
ps aux | grep apache2 # or httpd
Performance monitoring and optimization
Monitor your Apache HTTP/2 performance and implement additional optimizations. You can integrate with existing monitoring solutions like Prometheus and Grafana for comprehensive metrics collection.
Enable Apache status module
Configure server status monitoring for performance analysis.
sudo a2enmod status
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| HTTP/2 not working | SSL not properly configured | Verify SSL certificate and enable SSL engine |
| High memory usage | MPM settings too aggressive |
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default values
DOMAIN="${1:-example.com}"
EMAIL="${2:-admin@${DOMAIN}}"
# Usage message
usage() {
echo "Usage: $0 [domain] [email]"
echo "Example: $0 mydomain.com admin@mydomain.com"
exit 1
}
# Logging functions
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Check if running as root
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
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_CONF_DIR="/etc/apache2"
APACHE_SITES_DIR="/etc/apache2/sites-available"
APACHE_MODS_DIR="/etc/apache2/mods-available"
APACHE_DOC_ROOT="/var/www/html"
FIREWALL_CMD="ufw"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
APACHE_SERVICE="httpd"
APACHE_CONF_DIR="/etc/httpd"
APACHE_SITES_DIR="/etc/httpd/conf.d"
APACHE_MODS_DIR="/etc/httpd/conf.modules.d"
APACHE_DOC_ROOT="/var/www/html"
FIREWALL_CMD="firewall-cmd"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
APACHE_SERVICE="httpd"
APACHE_CONF_DIR="/etc/httpd"
APACHE_SITES_DIR="/etc/httpd/conf.d"
APACHE_MODS_DIR="/etc/httpd/conf.modules.d"
APACHE_DOC_ROOT="/var/www/html"
FIREWALL_CMD="firewall-cmd"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution"
exit 1
fi
# Cleanup function
cleanup() {
log_error "Installation failed. Cleaning up..."
systemctl stop $APACHE_SERVICE 2>/dev/null || true
systemctl disable $APACHE_SERVICE 2>/dev/null || true
}
trap cleanup ERR
log_info "[1/8] Updating system packages..."
$PKG_UPDATE
log_info "[2/8] Installing Apache and SSL packages..."
if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
$PKG_INSTALL apache2 apache2-utils ssl-cert openssl
else
$PKG_INSTALL httpd mod_ssl openssl mod_http2
fi
log_info "[3/8] Enabling Apache modules..."
if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
a2enmod ssl http2 rewrite deflate expires headers cache cache_disk
else
# Enable modules for RHEL-based systems
sed -i 's/#LoadModule rewrite_module/LoadModule rewrite_module/' ${APACHE_MODS_DIR}/00-base.conf 2>/dev/null || true
echo "LoadModule http2_module modules/mod_http2.so" > ${APACHE_MODS_DIR}/10-http2.conf
fi
log_info "[4/8] Generating SSL certificate..."
mkdir -p /etc/ssl/private
chmod 700 /etc/ssl/private
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=${DOMAIN}"
chmod 600 /etc/ssl/private/apache-selfsigned.key
chmod 644 /etc/ssl/certs/apache-selfsigned.crt
log_info "[5/8] Configuring Apache main settings..."
cat > ${APACHE_CONF_DIR}/conf-available/http2-performance.conf << 'EOF' || cat > ${APACHE_CONF_DIR}/conf.d/http2-performance.conf << 'EOF'
# HTTP/2 Configuration
Protocols h2 h2c http/1.1
H2Direct on
H2Upgrade on
H2StreamMaxMemSize 512000
H2MaxSessionStreams 100
H2InitialWindowSize 65536
H2MaxWorkerIdleSeconds 600
# Performance Optimizations
ServerTokens Prod
ServerSignature Off
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
Timeout 300
# Compression Settings
<IfModule mod_deflate.c>
DeflateCompressionLevel 6
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|webp|ico|svg)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
# Cache Settings
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
</IfModule>
EOF
if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
a2enconf http2-performance
fi
log_info "[6/8] Creating SSL virtual host..."
if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
VHOST_FILE="${APACHE_SITES_DIR}/${DOMAIN}-ssl.conf"
else
VHOST_FILE="${APACHE_SITES_DIR}/${DOMAIN}-ssl.conf"
fi
cat > "$VHOST_FILE" << EOF
<VirtualHost *:443>
ServerName ${DOMAIN}
ServerAlias www.${DOMAIN}
DocumentRoot ${APACHE_DOC_ROOT}
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
# Modern SSL Configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# HTTP/2 Protocol
Protocols h2 http/1.1
# Security Headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
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"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN}_ssl_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN}_ssl_access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName ${DOMAIN}
ServerAlias www.${DOMAIN}
Redirect permanent / https://${DOMAIN}/
</VirtualHost>
EOF
if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
a2ensite ${DOMAIN}-ssl
fi
log_info "[7/8] Configuring firewall..."
if command -v ufw &> /dev/null; then
ufw --force enable
ufw allow 'Apache Full'
elif command -v firewall-cmd &> /dev/null; then
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
fi
log_info "[8/8] Starting and enabling Apache..."
systemctl enable $APACHE_SERVICE
systemctl restart $APACHE_SERVICE
# Verification checks
log_info "Verifying installation..."
if systemctl is-active --quiet $APACHE_SERVICE; then
log_info "✓ Apache is running"
else
log_error "✗ Apache is not running"
exit 1
fi
if ss -tlnp | grep -q ':443'; then
log_info "✓ SSL port 443 is listening"
else
log_warn "✗ SSL port 443 is not listening"
fi
if $APACHE_SERVICE -M 2>/dev/null | grep -q http2 || httpd -M 2>/dev/null | grep -q http2; then
log_info "✓ HTTP/2 module is loaded"
else
log_warn "✗ HTTP/2 module may not be loaded"
fi
log_info ""
log_info "Apache HTTP/2 configuration completed successfully!"
log_info "Domain: ${DOMAIN}"
log_info "SSL Certificate: Self-signed (replace with proper certificate for production)"
log_info "Configuration files:"
log_info " - Main config: ${APACHE_CONF_DIR}/"
log_info " - Virtual host: ${VHOST_FILE}"
log_info ""
log_warn "Next steps:"
log_warn "1. Replace self-signed certificate with a proper SSL certificate"
log_warn "2. Update DocumentRoot and add your website content"
log_warn "3. Test HTTP/2 functionality with: curl -I --http2 https://${DOMAIN}/"
Review the script before running. Execute with: bash install.sh