Set up Apache HTTP Server with HTTP/2 protocol support and automatic SSL certificate management using Certbot. This tutorial covers virtual host configuration, SSL termination, and performance optimization for production websites.
Prerequisites
- Root or sudo access
- Domain name pointing to your server
- Port 80 and 443 open in firewall
What this solves
Apache HTTP Server with HTTP/2 provides faster page loading through request multiplexing and server push capabilities. SSL termination handles HTTPS encryption at the web server level, offloading cryptographic work from backend applications. Let's Encrypt certificates provide free, automated SSL/TLS encryption that renews automatically.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you get the latest Apache version with HTTP/2 support.
sudo apt update && sudo apt upgrade -y
Install Apache and SSL modules
Install Apache HTTP Server with essential SSL and HTTP/2 modules. The installation includes mod_ssl for SSL termination and mod_http2 for HTTP/2 protocol support.
sudo apt install -y apache2 apache2-utils
sudo a2enmod ssl
sudo a2enmod http2
sudo a2enmod headers
sudo a2enmod rewrite
Install Certbot for Let's Encrypt certificates
Certbot automates the process of obtaining and renewing Let's Encrypt SSL certificates. Install the Apache plugin for seamless integration.
sudo apt install -y certbot python3-certbot-apache
Configure main Apache settings
Update the main Apache configuration to enable HTTP/2 globally and optimize performance settings. This configuration enables HTTP/2 for all SSL-enabled virtual hosts.
# Enable HTTP/2 protocol
Protocols h2 h2c http/1.1
HTTP/2 performance settings
H2MaxSessionStreams 100
H2InitialWindowSize 65536
H2MaxFrameSize 16384
H2StreamMaxMemSize 65536
Enable HTTP/2 server push
H2Push on
H2PushPriority * after
H2PushPriority text/css before
H2PushPriority image/jpeg after 32
H2PushPriority application/javascript interleaved
sudo a2enconf http2
Create virtual host configuration
Set up a virtual host that will handle both HTTP and HTTPS traffic. This configuration redirects HTTP to HTTPS and prepares for SSL certificate installation.
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# Redirect all HTTP to HTTPS
Redirect permanent / https://example.com/
ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# SSL Engine
SSLEngine on
# HTTP/2 Protocol
Protocols h2 http/1.1
# Security Headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Performance optimizations
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Enable compression
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
# Browser caching
ExpiresActive On
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ErrorLog ${APACHE_LOG_DIR}/example.com_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_ssl_access.log combined
Create document root directory
Create the web directory with proper ownership and permissions. The www-data user needs read access to serve files, and you need write access to manage content.
sudo mkdir -p /var/www/example.com
sudo chown -R $USER:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com
Create a test page
Add a simple HTML page to test the configuration. This page includes HTTP/2 server push directives for optimal performance.
Apache HTTP/2 Test
Apache HTTP/2 with SSL
This site is running on Apache with HTTP/2 and Let's Encrypt SSL certificates.
Protocol:
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f4f4f4;
}
h1 {
color: #333;
text-align: center;
}
p {
line-height: 1.6;
color: #666;
}
Enable the virtual host
Activate the virtual host configuration and enable required Apache modules for optimal performance.
sudo a2ensite example.com.conf
sudo a2enmod deflate
sudo a2enmod expires
sudo apache2ctl configtest
sudo systemctl reload apache2
Configure firewall
Open HTTP and HTTPS ports in the firewall. Port 80 is needed for Let's Encrypt validation, and port 443 for HTTPS traffic.
sudo ufw allow 'Apache Full'
sudo ufw status
Obtain Let's Encrypt SSL certificates
Use Certbot to automatically obtain and install SSL certificates. This command will modify your Apache configuration to include the SSL certificate paths and enable HTTPS.
sudo certbot --apache -d example.com -d www.example.com
Optimize SSL configuration
Update the SSL configuration for enhanced security and performance. This includes modern cipher suites and SSL protocols.
# SSL Protocol support
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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
OCSP Stapling
SSLUseStapling On
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
SSL Compression
SSLCompression off
Performance optimizations
SSLSessionCache "shmcb:logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300
sudo a2enconf ssl-params
sudo systemctl reload apache2
Set up automatic certificate renewal
Configure automatic renewal of Let's Encrypt certificates. Certificates expire every 90 days and must be renewed regularly.
sudo crontab -e
Add this line to run renewal checks twice daily:
0 12,0 * /usr/bin/certbot renew --quiet --post-hook "systemctl reload apache2"
Test the renewal process:
sudo certbot renew --dry-run
Configure HTTP/2 server push
Add HTTP/2 server push directives to preload critical resources. This improves page load performance by pushing resources before the browser requests them.
# HTTP/2 Server Push
# Push critical CSS
Header add Link "; rel=preload; as=style"
# Enable early hints
H2EarlyHints on
Compression for text files
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
Verify your setup
Test your Apache HTTP/2 and SSL configuration with these verification commands:
# Check Apache status and loaded modules
sudo systemctl status apache2
sudo apache2ctl -M | grep -E "(ssl|http2|headers)"
Test SSL certificate
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
Check HTTP/2 protocol support
curl -I -k --http2 https://example.com
Test certificate renewal
sudo certbot certificates
Verify virtual host configuration
sudo apache2ctl -S
Visit your domain in a web browser and check the developer tools Network tab to confirm HTTP/2 protocol usage. Look for "h2" in the Protocol column.
Performance optimization
Enable mod_pagespeed (optional)
Google's mod_pagespeed automatically optimizes web pages and resources. Install it for additional performance improvements.
wget -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
echo "deb [arch=amd64] http://dl.google.com/linux/mod-pagespeed/deb/ stable main" | sudo tee /etc/apt/sources.list.d/mod-pagespeed.list
sudo apt update
sudo apt install -y mod-pagespeed-stable
sudo systemctl restart apache2
Configure worker settings
Optimize Apache worker processes for better concurrent connection handling with HTTP/2.
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 10000
sudo systemctl restart apache2
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| HTTP/2 not working | mod_http2 not loaded | sudo a2enmod http2 && sudo systemctl restart apache2 |
| SSL certificate errors | Firewall blocking port 80 | sudo ufw allow 80/tcp or check DNS settings |
| "AH00558" error message | Missing ServerName directive | Add ServerName example.com to virtual host |
| Permission denied errors | Wrong file ownership | sudo chown -R www-data:www-data /var/www/example.com |
| Certbot renewal fails | Apache config syntax error | sudo apache2ctl configtest to check configuration |
| Browser shows HTTP/1.1 | SSL not properly configured | Check certificate installation with sudo certbot certificates |
Monitoring and logging
For comprehensive monitoring of your Apache HTTP/2 setup, consider implementing log analysis and performance tracking. You can implement Apache log analysis with GoAccess and ELK stack for real-time monitoring or set up Apache reverse proxy and load balancing for high availability scenarios.
Next steps
- Configure Apache reverse proxy and load balancing for high availability
- Implement Apache web application firewall with ModSecurity 3 and OWASP Core Rule Set
- Set up Apache monitoring with Prometheus and Grafana dashboards
- Configure Apache multi-site SSL virtual hosts with wildcard certificates
- Implement Apache rate limiting and DDoS protection with mod_security and mod_evasive
Running this in production?
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'
# Usage message
usage() {
echo "Usage: $0 <domain> [email]"
echo "Example: $0 example.com admin@example.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"; }
# Cleanup function
cleanup() {
if [[ $? -ne 0 ]]; then
log_error "Installation failed. Rolling back changes..."
systemctl stop $APACHE_SERVICE 2>/dev/null || true
systemctl disable $APACHE_SERVICE 2>/dev/null || true
fi
}
trap cleanup ERR
# Check arguments
if [[ $# -lt 1 || $# -gt 2 ]]; then
usage
fi
DOMAIN="$1"
EMAIL="${2:-webmaster@$DOMAIN}"
# Validate domain format
if ! [[ "$DOMAIN" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
log_error "Invalid domain format: $DOMAIN"
exit 1
fi
# Check root privileges
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
# Detect distribution
if [[ ! -f /etc/os-release ]]; then
log_error "Cannot detect OS distribution"
exit 1
fi
. /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="$APACHE_CONFIG_DIR/sites-available"
ENABLE_SITE="a2ensite"
ENABLE_MOD="a2enmod"
APACHE_USER="www-data"
;;
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="$APACHE_CONFIG_DIR/conf.d"
ENABLE_SITE=""
ENABLE_MOD=""
APACHE_USER="apache"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
APACHE_SERVICE="httpd"
APACHE_CONFIG_DIR="/etc/httpd"
SITES_DIR="$APACHE_CONFIG_DIR/conf.d"
ENABLE_SITE=""
ENABLE_MOD=""
APACHE_USER="apache"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
WEB_ROOT="/var/www/$DOMAIN"
log_info "[1/8] Updating system packages..."
$PKG_UPDATE
log_info "[2/8] Installing Apache and SSL modules..."
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL apache2 apache2-utils
$ENABLE_MOD ssl
$ENABLE_MOD http2
$ENABLE_MOD headers
$ENABLE_MOD rewrite
$ENABLE_MOD expires
$ENABLE_MOD deflate
else
$PKG_INSTALL httpd httpd-tools mod_ssl
systemctl enable $APACHE_SERVICE
fi
log_info "[3/8] Installing Certbot..."
$PKG_INSTALL certbot python3-certbot-apache
log_info "[4/8] Configuring HTTP/2 settings..."
if [[ "$PKG_MGR" == "apt" ]]; then
HTTP2_CONF="$APACHE_CONFIG_DIR/conf-available/http2.conf"
else
HTTP2_CONF="$APACHE_CONFIG_DIR/conf.d/http2.conf"
fi
cat > "$HTTP2_CONF" << 'EOF'
# Enable HTTP/2 protocol
Protocols h2 h2c http/1.1
# HTTP/2 performance settings
H2MaxSessionStreams 100
H2InitialWindowSize 65536
H2MaxFrameSize 16384
H2StreamMaxMemSize 65536
# Enable HTTP/2 server push
H2Push on
H2PushPriority * after
H2PushPriority text/css before
H2PushPriority image/jpeg after 32
H2PushPriority application/javascript interleaved
EOF
if [[ "$PKG_MGR" == "apt" ]]; then
a2enconf http2
fi
log_info "[5/8] Creating document root..."
mkdir -p "$WEB_ROOT"
chown -R "$APACHE_USER:$APACHE_USER" "$WEB_ROOT"
chmod -R 755 "$WEB_ROOT"
# Create a simple index.html
cat > "$WEB_ROOT/index.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Welcome to $DOMAIN</title>
</head>
<body>
<h1>Welcome to $DOMAIN</h1>
<p>Apache HTTP/2 with SSL is configured successfully!</p>
</body>
</html>
EOF
chown "$APACHE_USER:$APACHE_USER" "$WEB_ROOT/index.html"
chmod 644 "$WEB_ROOT/index.html"
log_info "[6/8] Creating virtual host configuration..."
if [[ "$PKG_MGR" == "apt" ]]; then
VHOST_FILE="$SITES_DIR/$DOMAIN.conf"
else
VHOST_FILE="$SITES_DIR/$DOMAIN.conf"
fi
cat > "$VHOST_FILE" << EOF
<VirtualHost *:80>
ServerName $DOMAIN
ServerAlias www.$DOMAIN
DocumentRoot $WEB_ROOT
# Redirect all HTTP to HTTPS
Redirect permanent / https://$DOMAIN/
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN}_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN}_access.log combined
</VirtualHost>
<VirtualHost *:443>
ServerName $DOMAIN
ServerAlias www.$DOMAIN
DocumentRoot $WEB_ROOT
# SSL Engine
SSLEngine on
# HTTP/2 Protocol
Protocols h2 http/1.1
# Security Headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
<Directory $WEB_ROOT>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Enable compression
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
</IfModule>
# Browser caching
<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 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
</IfModule>
</Directory>
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN}_ssl_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN}_ssl_access.log combined
</VirtualHost>
EOF
chmod 644 "$VHOST_FILE"
if [[ "$PKG_MGR" == "apt" ]]; then
$ENABLE_SITE "$DOMAIN"
fi
log_info "[7/8] Starting and enabling Apache..."
systemctl enable $APACHE_SERVICE
systemctl restart $APACHE_SERVICE
# Configure firewall
if command -v ufw >/dev/null 2>&1; then
ufw allow 'Apache Full' || true
elif command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
fi
log_info "[8/8] Obtaining Let's Encrypt certificate..."
certbot --apache -d "$DOMAIN" -d "www.$DOMAIN" --non-interactive --agree-tos --email "$EMAIL" --redirect
# Set up auto-renewal
if ! crontab -l 2>/dev/null | grep -q certbot; then
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
fi
# Final verification
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 curl -s -I "http://$DOMAIN" | grep -q "301\|302"; then
log_info "✓ HTTP redirect is working"
else
log_warn "⚠ HTTP redirect may not be working"
fi
log_info "Installation completed successfully!"
log_info "Your site should now be accessible at https://$DOMAIN"
log_info "Certificate auto-renewal has been configured"
Review the script before running. Execute with: bash install.sh