All guides

LEARN \u00b7 DEBUGGING GUIDE

SSL certificate error after deployment: how to debug TLS issues

You deploy an update. Suddenly the site shows a certificate warning. 'Your connection is not private'. The certificate was fine yesterday.

IntermediateDocker/deployment debugging

What this usually means

SSL certificates have a finite lifespan. Let's Encrypt certificates last 90 days, paid certificates typically 1 year. If the certificate expired and auto-renewal failed, browsers reject it. If the deployment changed the domain, the certificate names no longer match. If the deployment changed how TLS is terminated, the certificate might not be installed in the new location.

( 01 )Fast diagnosis

The first ten minutes \u2014 establish facts before touching code.

  • 1Check the certificate expiry date. Click the padlock in the browser, or use: openssl s_client -connect example.com:443 -servername example.com | openssl x509 -noout -dates
  • 2Check the certificate names. Does the domain you are accessing match one of the names on the certificate?
  • 3Check if the certificate changed during deployment. Compare serial numbers before and after.
  • 4Check where TLS is terminated: CDN, load balancer, reverse proxy, or application server? Is the certificate there?
  • 5Check if auto-renewal is working. Are certbot or ACME renewal jobs running successfully?
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchBrowser Certificate Viewer — expiry date, subject, issuer, SANs
  • searchCertificate files on the server
  • searchLoad balancer or reverse proxy config — ssl_certificate directives
  • searchCDN or platform TLS settings — Cloudflare SSL mode, Vercel/Render auto SSL
  • searchAuto-renewal logs — certbot logs, Let's Encrypt renewal cron job output
  • searchDNS records — did the A or CNAME record change during deployment?
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningCertificate expired — renewal failed silently
  • warningCertificate was renewed but the server was not reloaded
  • warningDomain changed without updating the certificate
  • warningTLS termination point changed without installing the certificate at the new location
  • warningIntermediate certificate missing — only the leaf certificate is served
  • warningPrivate key and certificate mismatch after renewal
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildSet up certificate expiry monitoring that alerts 30 days before expiry
  • buildUse a platform with managed SSL that handles renewal automatically
  • buildIf using certbot, verify the renewal cron job runs and logs success
  • buildAfter renewing a certificate, reload the server that uses it
  • buildInclude the full certificate chain (leaf plus intermediate) in the server config
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedVisit the site over HTTPS. The padlock should show a valid certificate.
  • verifiedCheck the certificate expiry date is in the future.
  • verifiedTest with curl -vI https://example.com and look for successful SSL verification.
  • verifiedRun an SSL checker to verify the full chain and configuration.
  • verifiedTest on different networks and browsers to rule out local caching issues.
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningNot monitoring certificate expiry
  • warningRenewing a certificate but not reloading the server
  • warningMoving TLS termination to a different service without moving the certificate
  • warningNot including the intermediate certificate in the server config
  • warningAssuming the platform auto-SSL will always work