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 httpd

Basic 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.3

Modern 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:prime256v1

Compression settings

Disable SSL compression to prevent CRIME attack:

# Disable SSL compression
SSLCompression off

# Apache 2.4.26+ with OpenSSL 1.0.2+
SSLOpenSSLConfCmd Options -Compression

HSTS and Security Headers

Enable headers module

Required for security headers:

# Debian/Ubuntu
a2enmod headers

# RHEL/CentOS - usually enabled by default

Complete 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 off

Test 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 off

Client 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 require

SNI 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 3600

HTTP/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/CentOS

Check 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_3

SSL Labs test

Comprehensive SSL analysis:

# Visit: https://www.ssllabs.com/ssltest/
# Target: A+ rating with modern configuration

Important Notes

Module Dependencies:

SSL requires mod_ssl. Headers require mod_headers. HTTP/2 requires mod_http2. Enable with a2enmod on Debian/Ubuntu.

Configuration Files:

Debian/Ubuntu: /etc/apache2/sites-available/, /etc/apache2/mods-available/

RHEL/CentOS: /etc/httpd/conf.d/, /etc/httpd/conf/httpd.conf

Certificate Updates:

Use graceful reload (`systemctl reload apache2`) when updating certificates - no downtime.

SNI Support:

Apache 2.2.12+ supports SNI. Older versions require one IP per certificate.

OCSP Stapling:

Requires Apache 2.3.3+. Cache must be configured globally, not per virtual host.

HTTP/2:

Requires Apache 2.4.17+. Works with mod_mpm_event or mod_mpm_worker (not prefork).

Certificate Permissions:

Private keys should be readable only by Apache user (chmod 600, chown www-data or apache).

Documentation:

Official Apache SSL docs: httpd.apache.org/docs/current/mod/mod_ssl.html

Mozilla SSL Config Generator: ssl-config.mozilla.org

See Also