mod_ssl building blocks
mod_ssl terminates TLS in the same process model as your MPM. A minimal vhost enables the engine and points at a leaf + chain presentation to clients: today’s practice is a single PEM containing the server certificate followed by intermediates (what Let’s Encrypt calls fullchain.pem), plus a separate private key file with strict permissions.
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/www.example.com-fullchain.pem
SSLCertificateKeyFile /etc/pki/tls/private/www.example.com.keyOlder examples split SSLCertificateChainFile; on current Apache/OpenSSL combinations the chain file directive is often unnecessary if intermediates are already concatenated into SSLCertificateFile—verify against your distribution’s documentation to avoid sending an incomplete chain (clients fail with “unable to get local issuer”).
Protocols, cipher suites, and OpenSSL groups
Use SSLProtocol (or SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 style exclusions) and SSLCipherSuite together with Mozilla’s “modern” or “intermediate” profile for your client matrix. For OpenSSL 1.1.1+, SSLOpenSSLConfCmd Curves X25519:prime256v1 (example) tunes ECDHE groups without recompiling. SSLHonorCipherOrder On still matters for TLS1.2 mixed deployments; TLS 1.3 cipher order is largely negotiated by the library.
| Directive | Purpose |
|---|---|
SSLProtocol | Minimum/maximum TLS versions offered |
SSLCipherSuite | Allowed OpenSSL cipher names for TLS1.2 and below |
SSLCompression off | Disables TLS compression (CRIME class concerns on legacy stacks) |
SSLSessionCache | Server-side TLS session cache (shmcb file path and size) |
SSLSessionTickets | Ticket-based resumption—rotate keys on compromise; some hardening guides disable |
SNI and multiple certificates
Apache selects among <VirtualHost *:443> blocks using SNI during the TLS handshake. Each name (or shared wildcard) needs a matching cert or clients receive warnings. Wildcard certs do not cover sibling domains (*.a.example.com does not cover b.example.com). Test with openssl s_client -connect host:443 -servername host for each alias.
OCSP stapling
Stapling ships a recent OCSP response inside the handshake, reducing client latency and issuer load. Minimum viable pattern:
SSLUseStapling On
SSLStaplingCache shmcb:/run/httpd/ssl_stapling(32768)
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors OffApache must reach the CA’s OCSP URL over the network—firewall egress to high-numbered UDP/TCP resolvers is not enough; explicit HTTP proxies need SSLStaplingForceURL only as a last resort. If stapling fails, clients still validate via live OCSP/CRL unless you pinned “must-staple” in the certificate—understand your CA’s behavior before enabling aggressive error surfacing.
HSTS and application headers
Emit Strict-Transport-Security only on HTTPS responses once all subdomains are TLS-clean:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"includeSubDomains and HSTS preload submissions are commitments—broken TLS on any subdomain bricks clients until max-age expires. Pair with header strategy discussions for CSP and clickjacking protections.
Mutual TLS (client certificates)
SSLVerifyClient require on a vhost or location demands a client cert signed by a CA you trust via SSLCACertificateFile or SSLCADNRequestFile. optional_no_ca is rarely what operators assume—read mod_ssl docs before using. For attribute-based auth, map DN or SAN into headers with SSLUserName / RequestHeader set REMOTE_USER patterns carefully validated in the app.
Reverse proxy TLS to origin
When Apache proxies to another HTTPS service, configure trust explicitly:
SSLProxyEngine On
SSLProxyVerify on
SSLProxyVerifyDepth 3
SSLProxyCACertificateFile /etc/pki/tls/certs/ca-trust.pemDisabling verification “temporarily” in production creates an active attacker path—use a private CA or hash pinning where automated rotation is controlled. See Apache configuration for hook ordering with mod_proxy.
Enterprise operations
Automate renewals (ACME hooks), reload Apache gracefully after cert updates, and monitor expiry independently of the CA. Log TLS protocol and cipher via CustomLog format tokens such as %{SSL_PROTOCOL}x / %{SSL_CIPHER}x where available. Ship logs without leaking session IDs in query strings.
Related: virtual hosts, common TLS errors.