Short answer
A secure Apache TLS setup uses SSLCertificateFile with a fullchain file (or a separate SSLCertificateChainFile on older versions), sets SSLProtocol to TLSv1.2 and TLSv1.3 only, a short SSLCipherSuite with forward secrecy, enables OCSP stapling and HSTS. You reload with zero downtime using apachectl graceful.
The complete VirtualHost
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
SSLEngine on
# Fullchain file (leaf + intermediates). On httpd < 2.4.8
# use a separate SSLCertificateChainFile instead.
SSLCertificateFile /etc/ssl/example.com/fullchain.pem
SSLCertificateKeyFile /etc/ssl/example.com/privkey.pem
# Modern protocols only
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Strong ciphers with forward secrecy; let the server decide
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 on
# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</VirtualHost>
# OCSP stapling is configured globally (outside the VirtualHost)
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/ocsp(128000)"
# Redirect HTTP to HTTPS
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
The certificate chain: fullchain vs SSLCertificateChainFile
From httpd 2.4.8, SSLCertificateFile can contain the whole chain (leaf + intermediates) in one file — use fullchain.pem. On older versions you must supply intermediates separately with SSLCertificateChainFile. If you forget the chain, non-browser clients fail with "unable to get local issuer certificate" — see also the certificate chain explained.
SSLProtocol: turn everything legacy off
SSLProtocol -all +TLSv1.2 +TLSv1.3 explicitly disables everything and adds only the two modern versions. This is more robust than listing the legacy ones as -SSLv3 -TLSv1, because new insecure protocols are not allowed by default.
Ciphers and OCSP stapling
Keep SSLCipherSuite short and restricted to AEAD ciphers with ECDHE (forward secrecy). For TLS 1.3 the ciphers are fixed and not controlled by this directive. SSLUseStapling must sit in the global configuration, not inside the VirtualHost, and requires a stapling cache. Read more about cipher suites and OCSP stapling.
Test and graceful reload
# Validate the configuration sudo apachectl configtest # Graceful reload — in-flight requests finish first sudo apachectl graceful # Confirm what is served openssl s_client -connect example.com:443 -servername example.com
More on swapping the certificate without dropping connections in certificate rotation without downtime, and on keeping it renewed automatically in the ACME pillar.
How CertControl verifies your Apache endpoints
Apache configurations often drown in old, copied directives — and a forgotten graceful means the old certificate is still served. CertControl scans the endpoint from the outside and confirms that the chain is complete, that only modern protocols are offered, and that the certificate is not about to expire — independent of what the configuration file says.
Frequently asked questions
Should intermediates go in SSLCertificateFile or SSLCertificateChainFile?
From httpd 2.4.8 you can put the whole chain in SSLCertificateFile (use fullchain.pem). On older versions you supply intermediates separately in SSLCertificateChainFile.
What does SSLProtocol -all +TLSv1.2 +TLSv1.3 mean?
It turns off all protocols and then adds only TLS 1.2 and 1.3. This is the safest form, because it does not inadvertently allow legacy or future insecure protocols.
Where is OCSP stapling configured in Apache?
SSLUseStapling and SSLStaplingCache belong in the global server configuration, not inside the individual VirtualHost. The cache is shared across hosts.
What is the difference between apachectl graceful and restart?
graceful lets each child process finish its current request before being reloaded with the new configuration — no connections are dropped. A restart interrupts everything immediately.
Should I set SSLHonorCipherOrder?
With TLS 1.2 it can make sense to let the server decide the order via SSLHonorCipherOrder on. For TLS 1.3 it has no effect, as cipher selection is handled differently.