What the message looks like
curl: (60) SSL certificate problem: certificate has expiredCommon causes
- Automatic renewal failed, e.g. port 80 blocked or DNS changed.
- The certificate was renewed, but nginx, Postfix or Dovecot was not reloaded.
- The certbot timer or cron job no longer exists, e.g. after a migration.
- The certificate was copied by hand and lives outside
/etc/letsencrypt/live. - The client clock is wrong – then even a valid certificate looks expired.
Check
- Show the validity of the certificate actually served
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates - Show expiry dates of certbot certificates
certbot certificates 2>/dev/null | grep -E 'Certificate Name|Expiry' - Check that the renewal timer is active
systemctl list-timers | grep -i certbot - Test renewal without fetching real certificates
certbot renew --dry-run
Fix
- Renew now:
certbot renewand reload the service. - Make the reload permanent:
--deploy-hook 'systemctl reload nginx'or a script in/etc/letsencrypt/renewal-hooks/deploy/. - Fix errors from
certbot renew --dry-run, typically firewall, DNS or changed vhosts. - Monitor expiry dates – a warning 14 days before expiry is enough.
- On mail servers remember that Postfix and Dovecot need a reload too.
FAQ
Why is the certificate expired although certbot renewed it?
The service keeps the old certificate in memory. Without a reload nginx keeps serving the old one even though the file on disk is new.
Can an intermediate certificate expire?
Yes. If the server sends an outdated chain, clients fail despite a valid server certificate. Always use the current fullchain.pem.