Guide
Apache mod_ssl certificate expiry
Resolve apache mod_ssl certificate expired on httpd: VirtualHost SSLEngine paths, mod_ssl stapling, grace reload, and openssl proof after renew.
Updated May 30, 2026 820 words
apache mod_ssl certificate expired means httpd’s VirtualHost still points SSLEngine at a leaf past notAfter—browsers see Apache’s name in errors even when operators renewed files elsewhere on the server.
Linux admins running RHEL, Debian, or Ubuntu stacks often maintain multiple SSL directives across default configs, name-based vhosts, and reverse proxies. mod_ssl loads the first matching VirtualHost on an IP:port combination; renewing one file does not change another SSLCertificateFile path still referenced in production.
apache mod_ssl certificate expired troubleshooting follows disk paths, running config, and live handshake evidence in that order. Reload gracefully after PEM swaps so existing connections drain without refusing new ones on stale material.
Shared hosting panels sometimes write SSL directives into panel-managed includes that overwrite manual edits on upgrade. apache mod_ssl certificate expired after a control panel update often means the panel reverted paths to vendor defaults. Compare panel-managed paths with grep SSLCertificate output before reclosing tickets.
Document whether httpd uses mpm_event, prefork, or worker because reload behavior and long-lived connections differ during rotation. High-traffic shops schedule reloads during maintenance windows even when graceful reload is technically sufficient.
What to check
Enumerate active SSLEngine on blocks with apachectl -S and compare each SSLCertificateFile and SSLCertificateKeyFile path to renewed PEM locations.
When multiple vhosts serve the same IP, verify ServerName and ServerAlias coverage matches the certificate SAN list—expiry errors can mask hostname mismatch until dates are fixed.
Check whether mod_ssl still references expired chain files via SSLCertificateChainFile or bundled fullchain paths. Chain-only updates do not fix an expired leaf.
Confirm httpd actually reloaded. Package updates sometimes restart unrelated units while httpd keeps workers holding previous mmap’d certificate bytes until graceful reload completes.
When httpd fronts Tomcat or PHP-FPM, confirm TLS terminates at httpd—not at a backend listener on another port you openssl tested by habit.
Step-by-step
Map vhosts and certificate paths
sudo apachectl -S
sudo apachectl -t -D DUMP_VHOSTS 2>/dev/null | grep -E '443|SSL'
grep -R SSLCertificateFile /etc/httpd /etc/apache2 2>/dev/null
On Debian-family hosts, look under sites-enabled and conf-enabled.
Inspect PEM dates on disk
sudo openssl x509 -in /etc/letsencrypt/live/example/fullchain.pem -noout -dates -serial
sudo openssl x509 -in /etc/ssl/certs/example.crt -noout -dates -serial
Confirm what the internet receives
HOST=www.example.com
echo | openssl s_client -connect "${HOST}:443" -servername "${HOST}" 2>/dev/null \
| openssl x509 -noout -dates -subject -issuer -serial
Renew and align VirtualHost directives
For Certbot-managed sites:
sudo certbot renew --cert-name example.com
sudo certbot certificates
Ensure SSLCertificateFile references fullchain.pem (or leaf plus SSLCertificateChainFile) and SSLCertificateKeyFile references the matching private key.
Test syntax and reload
sudo apachectl configtest
sudo systemctl reload httpd # RHEL
sudo systemctl reload apache2 # Debian/Ubuntu
Re-run openssl and compare serial
Serial must change when you issued new material unless you performed an unusual rekeying exception.
SELinux and permission checks on RHEL
On hardened hosts, renewed PEM paths must keep httpd_sys_content_t context. Copying certs from admin home directories without restorecon yields intermittent loads or forbidden private key reads logged only at debug level. After renew, run appropriate AVC checks before declaring the rotation complete.
How to read the output
apachectl configtest syntax errors block reload—fix typos before assuming renewal failed. Syntax OK plus unchanged openssl serial means workers or wrong vhost still serve old PEM paths.
notAfter in the past on openssl output is the user-visible failure mode. subject should list the hostname you tested; if not, mod_ssl may be serving a default vhost cert while you updated a different file.
apachectl -S warnings about ambiguous ServerNames hint that the wrong VirtualHost answered the handshake during your test—retry with explicit SNI using openssl s_client -servername.
issuer DN helps separate Let’s Encrypt automation from corporate MI certificates when multiple environments share a host.
Common mistakes
Editing default-ssl.conf while production traffic uses a distro-specific vhost in sites-available that still references last year’s crt path.
Mixing SSLCertificateFile leaf-only PEM without intermediates, causing chain errors mistaken for expiry until logs show both issues.
Running systemctl restart during peak without graceful considerations when mod_ssl supports reload—unnecessary but reload skipped is worse.
Renewing at the CA but omitting reload steps documented in reload Apache after SSL renewal guidance.
Assuming mod_md or other automation replaced Certbot without verifying mod_md certificate store paths on disk.
Chasing apache mod_ssl certificate expired when CDN edge certificates expired—always include an external openssl from off-network.
mod_ssl per-directory overrides in .htaccess rarely apply to initial handshake cert selection—teams chasing hotfix overrides miss VirtualHost-level expiry. During IPv6 rollout, verify separate :443 vhosts on v6 listeners reference the same renewed paths as legacy v4 blocks.
Corporate change boards appreciate before-and-after openssl transcripts stored with CAB tickets. That habit speeds audits when regulators ask how you proved apache mod_ssl certificate expired remediation within SLA windows.
When to use automation
httpd farms rarely centralize PEM inventory without configuration management drift. CMDB rows show renewed paths while one forgotten Include file still loads expired material.
ssldays inspects live TLS for each public hostname—expiry, issuer, SANs, and chain trust from the visitor’s perspective. RDAP supplements registration timelines when registries publish expiry fields. Email alerts at 30, 14, 7, and 1 days reduce surprise Friday night reloads. Starter and Pro add Slack and Discord webhooks. Free accounts monitor three domains daily; Starter 25 hourly; Pro 100 hourly.
Confirm remediation on live check, then register production names at register. When automation fails before expiry, start with certbot renew failed before opening commercial reissue tickets.
Frequently asked questions
Is systemctl reload enough?
Usually yes for PEM path changes. If openssl serial is stale after reload, use graceful restart per distribution docs.
Can mod_ssl use PKCS#11 or HSM paths?
Yes. Expiry then follows the token object lifecycle, not filesystem PEM dates—use vendor tools to read notAfter.
What about mod_proxy to Tomcat?
HTTPS might terminate on httpd while backends use HTTP. openssl still tests mod_ssl on port 443 at httpd.
Should I disable obsolete TLS versions first?
Protocol hardening is separate. Fix expired leaves first so monitoring and customers regain trust before cipher sunset projects.
Monitor this hostname on a schedule
Live certificate checks and renewal reminders — not guesswork from PEM files.