Apache SSL Certificate Installation: Virtual Hosts, Chains, and Renewals
Installing an SSL certificate on Apache is still a top support ticket for teams that left the “Shared SSL” era years ago but never standardized renewals. The httpd config is usually fine; the chain file is wrong, SSLCertificateKeyFile points at yesterday’s key, or HTTP-01 fails because the ACME challenge never hits the vhost you think it does.
This walkthrough covers a clean Apache TLS setup (2.4.x style), full-chain pitfalls, and how to keep renewals from becoming a quarterly fire drill.
What Apache Needs on Disk
For a typical modern distro layout you end up with three paths (names vary):
| File | Role |
|---|---|
privkey.pem / .key |
Private key — never web-accessible |
cert.pem / leaf .crt |
Server (leaf) certificate |
chain.pem / fullchain.pem |
Intermediate(s); often leaf+chain combined |
Apache 2.4.8+ prefers:
SSLEngine on
SSLCertificateFile /etc/ssl/example/fullchain.pem
SSLCertificateKeyFile /etc/ssl/example/privkey.pem
Older guides still mention SSLCertificateChainFile. If your build supports putting the chain in SSLCertificateFile (fullchain), do that and drop the separate chain directive—one less file to desync on renew.
Formats and when Windows wants PFX instead: PEM vs PFX install.
Minimal HTTPS Virtual Host
Example for example.com (adjust paths and ServerAlias):
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Modern baselines; tune to your crypto policy
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder off
</VirtualHost>
Enable the site, then:
apachectl configtest
systemctl reload apache2 # or httpd
configtest catching a missing key path before reload saves the “all vhosts died” afternoon.
HTTP → HTTPS and ACME Coexistence
Blindly forcing every request to HTTPS can break HTTP-01 challenges if the redirect fires before /.well-known/acme-challenge/ is served. Either:
- Exclude the challenge path from the redirect, or
- Terminate challenges on port 80 in a dedicated location, or
- Use DNS-01 and ignore webroot entirely (required for wildcards anyway).
Protocol comparison: HTTP-01 vs DNS-01.
A safe pattern many operators use:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example/html
Alias /.well-known/acme-challenge/ /var/www/letsencrypt/.well-known/acme-challenge/
<Directory /var/www/letsencrypt/.well-known/acme-challenge/>
Require all granted
</Directory>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Full Chain Mistakes That Look Like “Apache SSL Is Broken”
Browsers show scary UI when the intermediate is missing even if the leaf is perfect. Symptoms:
- Works on some corporate networks (that cache intermediates) and fails on mobile
openssl s_clientshowsverify error:num=20:unable to get local issuer certificate- SSL Labs: “Chain issues: Incomplete”
Fix: serve leaf + intermediate in the order your CA documents. Do not upload the root. Deep dive: incomplete SSL certificate chain.
Let's Encrypt on Apache vs Commercial Files
Certbot’s Apache plugin can edit vhosts for you. That is convenient on a single box and painful when config is templated by Ansible or when five people “help” by hand-editing the same file.
Commercial DV/OV arrives as zip/PEM. Installation steps are the same Apache directives; only issuance and DCV differ. Buying checklist: how to buy an SSL certificate. Free vs paid trade-offs: free SSL vs paid SSL.
For Nginx-heavy fleets the sibling guide is Linux NGINX SSL installation. Apache and Nginx share the same chain rules; only the directive names change.
Renewals: Reload Is Part of the Certificate
A renewed file on disk does nothing until Apache reloads. Wire renew hooks:
# example Certbot deploy hook idea
systemctl reload apache2
With lifetimes trending shorter (validity periods), missing the reload is as bad as missing the renew. Monitor notAfter and failed ACME jobs.
When a Control Plane Beats Per-Box Certbot
Certbot on every VM works until you add staging clones, shared storage oddities, and mixed Windows IIS edges. Then you want issuance in one place and deploy to Apache among other targets.
Certinite approaches Apache as a deployment target in a broader certificate lifecycle—not a one-off tutorial host. That matters when the same company also runs IIS agents or panel connectors (cPanel, Plesk).
FAQ
Do I need a separate certificate for www and the apex?
Not if both names are on the certificate (SAN). One leaf covering example.com and www.example.com is normal. Wildcards cover *.example.com but not the apex—see wildcard SSL automation.
Is SSLCertificateChainFile obsolete?
On current 2.4 builds, prefer fullchain in SSLCertificateFile. Keep SSLCertificateChainFile only when you are stuck on older packages and know why.
Why does Apache start but browsers still warn?
Often OCSP/CDN caching, wrong vhost (ServerName mismatch / missing SNI), or incomplete chain—not “Apache failed to read the cert.” Test with openssl s_client -servername and compare to the browser’s view of the certificate.
Can I use the same certificate on Apache and IIS?
Yes if both names and key usage match. Export carefully (PEM vs PFX). Prefer automation that deploys the same issuance to both stacks instead of copying secrets over chat.
Bottom Line
Apache SSL installation is mostly correct files + correct vhost + reload. The long-term problem is renewal under shrinking lifetimes. Get the chain right once, then put issuance and reload on a schedule you actually monitor.
Product path: Apache integration · pricing · primer what is an SSL certificate.