This guide installs an SSL certificate on Apache httpd 2.4 with a secure configuration, then covers renewal. Paths are for Debian and Ubuntu; on RHEL, Rocky and Fedora the main configuration lives in /etc/httpd/ and the service is called httpd.
Quickest path: Let's Encrypt with Certbot
sudo apt install certbot python3-certbot-apache # Debian/Ubuntu
sudo certbot --apache -d example.com -d www.example.com
Certbot creates the HTTPS virtual host and sets up renewal; see Renew Let's Encrypt with Certbot. Use the manual steps below for commercial certificates.
1. Enable the modules
sudo a2enmod ssl headers rewrite
On RHEL-based systems, install mod_ssl instead (sudo dnf install mod_ssl).
2. Put the certificate files in place
- Full chain: your certificate followed by the intermediate certificate(s):
cat your_domain.crt ca_bundle.crt > fullchain.crt. - Private key, readable only by root.
sudo mkdir -p /etc/ssl/example.com
sudo cp fullchain.crt example.com.key /etc/ssl/example.com/
sudo chmod 600 /etc/ssl/example.com/example.com.key
3. Configure the virtual hosts
Create /etc/apache2/sites-available/example.com-ssl.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
SSLEngine on
# Apache 2.4.8+: the full chain goes in SSLCertificateFile
SSLCertificateFile /etc/ssl/example.com/fullchain.crt
SSLCertificateKeyFile /etc/ssl/example.com/example.com.key
# TLS 1.3 needs Apache 2.4.36+ built with OpenSSL 1.1.1+
SSLProtocol -all +TLSv1.2 +TLSv1.3
Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>
Enable it:
sudo a2ensite example.com-ssl
On Apache older than 2.4.8, keep your own certificate in SSLCertificateFile and point SSLCertificateChainFile at the intermediate bundle. If the intermediate is left out entirely, browsers may still work while apps fail; see Fix an incomplete certificate chain.
For ciphers that suit your Apache and OpenSSL versions, use the Mozilla SSL Configuration Generator (Intermediate profile).
4. Test and reload
sudo apachectl configtest
sudo systemctl reload apache2 # httpd on RHEL/Fedora
configtest should print Syntax OK. Then check the site with the SSL checker: a complete chain, hostname match and only TLS 1.2/1.3 give grade A.
Renewing
Replace the certificate and key files at the same paths, then run configtest and reload. Apache keeps using the old certificate until it reloads. With Certbot's --apache plugin, renewals reload Apache automatically; with other methods, add a deploy hook.
Troubleshooting
SSL Library Error/ "key values mismatch" on start: the private key doesn't belong to the certificate.- Wrong certificate served: another virtual host on port 443 matches first. Check
ServerName/ServerAlias, and runsudo apachectl -Sto see which virtual host answers each name. - Old certificate still served after renewal: Apache wasn't reloaded, or a load balancer or CDN in front holds its own copy.
CertHalo checks your Apache sites on a schedule and emails you before the certificate expires. Monitor 3 certificates free.