Apache SSL/TLS Configuration
Best practices for configuring SSL/TLS in Apache HTTP Server with modern security standards and performance optimizations.
Basic HTTPS Virtual Host
Enable SSL module
First, enable the SSL module:
# Debian/Ubuntu
a2enmod ssl
a2ensite default-ssl
systemctl restart apache2
# RHEL/CentOS
# SSL module enabled by default in httpd
systemctl restart httpdBasic SSL virtual host
Minimal HTTPS configuration:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/example.com-chain.crt
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>HTTP to HTTPS redirect
Force all traffic to HTTPS:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>Modern Security Configuration
TLS protocols
Enable only TLS 1.2 and 1.3:
# Modern configuration (Apache 2.4.36+)
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# For older Apache versions
SSLProtocol TLSv1.2 TLSv1.3Modern cipher suites
Recommended cipher configuration for 2024+:
# Mozilla Intermediate profile
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
# For Apache 2.4.36+ with OpenSSL 1.1.1+
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1Compression settings
Disable SSL compression to prevent CRIME attack:
# Disable SSL compression
SSLCompression off
# Apache 2.4.26+ with OpenSSL 1.0.2+
SSLOpenSSLConfCmd Options -CompressionHSTS and Security Headers
Enable headers module
Required for security headers:
# Debian/Ubuntu
a2enmod headers
# RHEL/CentOS - usually enabled by defaultComplete security headers
Add to SSL virtual host:
# HSTS with 2-year max-age, includeSubDomains, and preload
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# 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"
# Clickjacking protection
Header always set X-Frame-Options "SAMEORIGIN"
# Referrer policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Content Security Policy (customize for your site)
Header always set Content-Security-Policy "default-src 'self' https:; script-src 'self'; style-src 'self' 'unsafe-inline'"
# Permissions Policy
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"OCSP Stapling
Enable OCSP stapling
Improve performance and privacy (Apache 2.3.3+):
# In ssl.conf or main Apache config
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStaplingStandardCacheTimeout 3600
SSLStaplingErrorCacheTimeout 600
# In virtual host
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors offTest OCSP stapling
Verify OCSP stapling is working:
# Using OpenSSL
echo QUIT | openssl s_client -connect example.com:443 -status 2>&1 | grep -A 17 'OCSP response:'
# Should show: OCSP Response Status: successful (0x0)SSL Session Management
Session cache configuration
Improve performance with session caching:
# Shared memory session cache
SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300
# Disable session tickets for forward secrecy
SSLSessionTickets offClient Certificate Authentication (mTLS)
Require client certificates
Enable mutual TLS authentication:
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
# Require client certificates
SSLCACertificateFile /etc/ssl/certs/client-ca.crt
SSLVerifyClient require
SSLVerifyDepth 2
</VirtualHost>Optional client certificates
Make client certs optional, check in application:
SSLCACertificateFile /etc/ssl/certs/client-ca.crt
SSLVerifyClient optional_no_ca
SSLVerifyDepth 2
# Pass client cert info to application
<Location />
SSLOptions +StdEnvVars +ExportCertData
</Location>CRL checking
Validate client certificates against CRL:
SSLCACertificateFile /etc/ssl/certs/client-ca.crt
SSLCARevocationFile /etc/ssl/crl/ca-crl.pem
SSLCARevocationCheck chain
SSLVerifyClient requireSNI and Multiple Certificates
Multiple virtual hosts
Different certificates for different domains:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
# ... site config
</VirtualHost>
<VirtualHost *:443>
ServerName api.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/api.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/api.example.com.key
# ... API config
</VirtualHost>Wildcard certificate
Single certificate for all subdomains:
<VirtualHost *:443>
ServerName *.example.com
ServerAlias *.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/wildcard.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/wildcard.example.com.key
# Use VirtualDocumentRoot for subdomain routing
VirtualDocumentRoot /var/www/%1.example.com
</VirtualHost>Complete Production Configuration
Hardened Apache SSL config
Complete example with all best practices:
# HTTP redirect to HTTPS
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
# HTTPS server
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# SSL Engine
SSLEngine on
# SSL Certificates
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/example.com-chain.crt
# SSL Protocols and Ciphers
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
SSLHonorCipherOrder off
SSLCompression off
# SSL Session
SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300
SSLSessionTickets off
# OCSP Stapling
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
# Security Headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Logging
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
# Document Root
<Directory /var/www/example.com>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
# Global SSL settings (in ssl.conf or apache2.conf)
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStaplingStandardCacheTimeout 3600HTTP/2 Configuration
Enable HTTP/2
Improve performance with HTTP/2 (Apache 2.4.17+):
# Enable http2 module
a2enmod http2
# Add to virtual host
Protocols h2 http/1.1
# Full example
<VirtualHost *:443>
ServerName example.com
Protocols h2 http/1.1
SSLEngine on
# ... SSL config
</VirtualHost>Testing and Validation
Test configuration
Validate Apache config before restart:
# Debian/Ubuntu
apachectl configtest
# or
apache2ctl configtest
# RHEL/CentOS
httpd -t
# If successful, reload
systemctl reload apache2 # Debian/Ubuntu
systemctl reload httpd # RHEL/CentOSCheck SSL configuration
Verify SSL settings:
# Test connection
openssl s_client -connect example.com:443 -servername example.com
# Check certificate
openssl s_client -connect example.com:443 -showcerts
# Test specific TLS version
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3SSL Labs test
Comprehensive SSL analysis:
# Visit: https://www.ssllabs.com/ssltest/
# Target: A+ rating with modern configurationImportant Notes
SSL requires mod_ssl. Headers require mod_headers. HTTP/2 requires mod_http2. Enable with a2enmod on Debian/Ubuntu.
Debian/Ubuntu: /etc/apache2/sites-available/, /etc/apache2/mods-available/
RHEL/CentOS: /etc/httpd/conf.d/, /etc/httpd/conf/httpd.conf
Use graceful reload (`systemctl reload apache2`) when updating certificates - no downtime.
Apache 2.2.12+ supports SNI. Older versions require one IP per certificate.
Requires Apache 2.3.3+. Cache must be configured globally, not per virtual host.
Requires Apache 2.4.17+. Works with mod_mpm_event or mod_mpm_worker (not prefork).
Private keys should be readable only by Apache user (chmod 600, chown www-data or apache).
Official Apache SSL docs: httpd.apache.org/docs/current/mod/mod_ssl.html
Mozilla SSL Config Generator: ssl-config.mozilla.org