Before You Start
Apache uses mod_ssl for TLS. You need three things:
- Certificate file (
SSLCertificateFile) -- your server's PEM certificate - Private key file (
SSLCertificateKeyFile) -- the matching private key - Chain file (
SSLCertificateChainFileor included in the cert) -- intermediate CA certificates
Don't have a certificate yet? Generate a test one at getaCert.com to follow along, or get a CA-signed certificate at /casign.
Enable mod_ssl
On Debian/Ubuntu:
sudo a2enmod ssl
sudo a2enmod headers
sudo systemctl restart apache2
On RHEL/CentOS:
sudo yum install mod_ssl
sudo systemctl restart httpd
Basic SSL Virtual Host
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.pem
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/chain.pem
</VirtualHost>
Test the config before restarting:
apachectl configtest
sudo systemctl reload apache2
Production-Ready Configuration
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.pem
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/chain.pem
# Modern TLS only
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
SSLHonorCipherOrder off
SSLSessionTickets off
# HSTS - tell browsers to always use HTTPS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
# OCSP Stapling
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
</VirtualHost>
# OCSP Stapling cache (must be outside VirtualHost)
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# Redirect HTTP to HTTPS
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
Installing a PKCS#12 (.p12) Certificate
If you downloaded a .p12 bundle from getaCert.com, extract the PEM files first:
# Extract the certificate
openssl pkcs12 -in certificate.p12 -clcerts -nokeys -out cert.pem
# Extract the private key
openssl pkcs12 -in certificate.p12 -nocerts -nodes -out key.pem
# Extract the CA chain (if included)
openssl pkcs12 -in certificate.p12 -cacerts -nokeys -out chain.pem
The default password for getaCert.com PKCS#12 files is password. Change it for production use.
Verify Your Configuration
After reloading Apache, test your SSL setup:
# Quick test
openssl s_client -connect example.com:443 -servername example.com
# Check certificate details
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -text -noout
# Or use our SSL checker
# https://getacert.com/check
Common Apache SSL Mistakes
Wrong file permissions
Apache needs to read the private key but nobody else should:
sudo chmod 600 /etc/ssl/private/example.com.key
sudo chown root:root /etc/ssl/private/example.com.key
Missing chain file
If browsers show "certificate not trusted" but the cert itself is valid, you're probably missing the intermediate chain. Either provide SSLCertificateChainFile separately or concatenate it into your cert file:
cat example.com.pem intermediate.pem > fullchain.pem
Mixed content after enabling HTTPS
Your site loads over HTTPS but images, scripts, or stylesheets still reference http://. Fix by using relative URLs or protocol-relative paths in your HTML, or add a Content-Security-Policy header:
Header set Content-Security-Policy "upgrade-insecure-requests"
Port 443 not listening
If Apache won't start with SSL, check that port 443 is configured in /etc/apache2/ports.conf:
Listen 443
Apache vs Nginx SSL Performance
Apache's mod_ssl and nginx's SSL implementation are both built on OpenSSL, so raw TLS performance is similar. The main differences:
- Apache prefork creates a new process per connection -- higher memory for many concurrent TLS sessions
- Apache event/worker MPM handles concurrent connections more efficiently, similar to nginx
- Session caching works differently: Apache uses
SSLSessionCache, nginx usesssl_session_cache
For most sites, the difference is negligible. Choose based on what you already run.
Next Steps
- Test your configuration with our SSL Checker
- Learn about certificate chain order -- a common source of errors
- Generate a CA-signed certificate for staging environments