All guides · Security

TLS Certificates: Trust, Expiry and Hostname Match

A TLS certificate proves to a browser that it is talking to the real owner of a hostname. It is issued by a certificate authority (CA) that browsers trust, it names the hostnames it is valid for, and it has a fixed expiry date. If any of those three things is wrong, the browser shows a full-page warning instead of your site.

Why it matters

Certificate errors are not cosmetic. A browser that cannot verify the certificate cannot rule out that someone is intercepting the connection, so it stops the visitor at an interstitial page. Most people leave at that point. APIs, payment callbacks, webhooks and mobile apps are stricter still: they usually fail the request outright.

Expiry is the most common cause, and it is almost always a process problem: a renewal that was done by hand, a cron job that silently stopped, or a certificate copied to one server but not another.

What we check

We open a TLS connection to port 443 of the scanned hostname (a handshake only, no HTTP request) and inspect the certificate it presents.

Check Passes when
Certificate is trusted the chain validates against a standard set of trusted root CAs
Certificate expiry the certificate is valid for more than 30 more days
Certificate matches the hostname the certificate’s names include the scanned hostname, directly or by wildcard

Expiry is reported as “needs attention” with 15 to 30 days left and as failing with 14 days or fewer. If the site is not served over HTTPS at all, these checks are shown as informational; see the HTTPS guide first. If the handshake itself fails, they are shown as “couldn’t test”.

How to fix

Certificate is not trusted

The usual causes, in order of likelihood:

  1. Missing intermediate certificate. The server sends only your certificate and not the intermediate that links it to the root. Some desktop browsers paper over this by fetching the intermediate themselves, so the site looks fine in your browser while other clients fail. Configure the server with the full chain file your CA provides.
  2. Self-signed or private-CA certificate. These are fine on internal networks but not on a public site. Replace it with one from a public CA.
  3. Expired or not-yet-valid certificate. See the expiry section below.

Nginx (Certbot and most ACME clients write a fullchain.pem for this purpose):

ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Apache 2.4.8 or newer:

SSLCertificateFile    /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

You can see exactly what the server sends with:

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null

The output should list your certificate followed by at least one intermediate.

Certificate is close to expiry

Automate renewal with an ACME client so no human has to remember it:

  • Let’s Encrypt with Certbot: installing Certbot from your distribution or via snap sets up a timer that renews certificates when about 30 days remain. Run certbot renew --dry-run to confirm it works.
  • Caddy and many hosting platforms obtain and renew certificates automatically.
  • CDNs such as Cloudflare issue and renew edge certificates for proxied hostnames.

After renewal, the web server must reload to pick up the new file. Certbot can do this with a deploy hook, for example --deploy-hook "systemctl reload nginx".

The CA/Browser Forum has voted to shorten the maximum lifetime of public certificates in stages over the next few years, so manual renewal will only become harder to sustain.

Certificate does not match the hostname

The certificate must list the exact hostname visitors use in its Subject Alternative Name field. example.com and www.example.com are different names: a certificate for one does not cover the other unless both are listed. A wildcard such as *.example.com covers www.example.com and shop.example.com, but not example.com itself and not a.b.example.com.

With Certbot, request every name you serve:

certbot --nginx -d example.com -d www.example.com

If you host several sites on one IP address, also check that each server block (Nginx) or VirtualHost (Apache) points at its own certificate. A mismatch often means the request fell through to a default site.

Keep an eye on it

  • Monitor expiry from outside your infrastructure, so you are alerted even if the renewal job and the server that runs it both fail.
  • Keep the private key readable only by the web server user, and never commit it to a repository.
  • When you move hosts or CDNs, check certificates on both example.com and www.example.com.

Further reading: MDN: Transport Layer Security.

Last updated October 24, 2026