TLS certificate errors are your server telling you it can’t establish a secure, encrypted connection because it doesn’t trust the identity of the client trying to connect, or vice-versa. This usually happens because one side presented a certificate that the other side can’t validate against its list of trusted Certificate Authorities (CAs).

Let’s say you’re seeing curl: (60) SSL certificate problem: unable to get local issuer certificate when trying to access an internal service from your workstation. This means curl (acting as the client) received a certificate from the server, but it can’t find the certificate of the Certificate Authority that signed the server’s certificate within its own collection of trusted CAs.

Here are the most common reasons this happens and how to fix them:

  1. The Server’s Certificate Isn’t Signed by a Trusted CA: The server is presenting a certificate that was signed by a private or internal CA, and your curl client doesn’t have that CA’s root certificate installed and trusted.

    • Diagnosis: On the server, run openssl x509 -in /etc/ssl/certs/your_server.crt -noout -issuer. This will show you the issuer of the server’s certificate. On your client machine, check if this issuer is in your system’s trusted CA store. For Linux, this is typically /etc/ssl/certs/ca-certificates.crt or /etc/pki/tls/certs/ca-bundle.crt. For macOS, it’s in Keychain Access. For Windows, it’s the Certificate Manager (certmgr.msc).
    • Fix: Obtain the root CA certificate that signed the server’s certificate. On your client machine, install this root CA certificate into your system’s trusted CA store. For example, on Ubuntu, you’d place the .crt file in /usr/local/share/ca-certificates/ and then run sudo update-ca-certificates. This makes your system trust any certificate issued by that CA.
    • Why it works: Your client now has the "stamp of approval" for the CA that issued the server’s certificate, so it trusts the server’s identity.
  2. Intermediate Certificates Are Missing on the Server: The server might have a valid certificate, but it’s not providing the "chain" of intermediate certificates that link its certificate back to a trusted root CA. Browsers and clients expect this chain.

    • Diagnosis: Use openssl s_client -connect your_server.com:443 -showcerts < /dev/null. Look at the output. If you see only one certificate (the server’s) and not a chain leading up to a root, this is the problem.
    • Fix: Concatenate your server’s certificate with its intermediate certificate(s) into a single file, usually named fullchain.pem or chained.crt. For example, if your server cert is your_server.crt and the intermediate is intermediate.crt, the file would be:
      cat your_server.crt intermediate.crt > fullchain.pem
      
      Then, configure your web server (e.g., Nginx ssl_certificate) or application to use this fullchain.pem instead of just your_server.crt.
    • Why it works: The client receives the full path from the server’s certificate all the way up to a root CA it already trusts, allowing it to validate the entire chain.
  3. Client is Using an Outdated CA Bundle: Your operating system or curl installation might be using a very old list of trusted CAs, and the CA that signed the server’s certificate is new or was not included in that old bundle.

    • Diagnosis: Check the modification date of your system’s CA bundle file (e.g., /etc/ssl/certs/ca-certificates.crt on Debian/Ubuntu). If it’s old (years), this could be the issue.
    • Fix: Update your system’s CA certificates. On Debian/Ubuntu: sudo apt update && sudo apt upgrade ca-certificates. On Red Hat/CentOS: sudo yum update ca-certificates. For curl specifically on some systems, you might need to explicitly tell it where to find the CA bundle using the --cacert option, pointing to your system’s CA file.
    • Why it works: A fresh CA bundle contains a more current and comprehensive list of trusted root certificates.
  4. Self-Signed Certificate (and client not configured to trust it): The server is using a certificate it generated itself, not one from a public or private CA.

    • Diagnosis: If you examine the server’s certificate, it will likely show the issuer and subject as the same entity.
    • Fix: You have two options:
      • Option A (Recommended for production): Replace the self-signed certificate with one issued by a trusted CA (public or private).
      • Option B (For development/testing only): Tell curl to trust this specific self-signed certificate using the --cacert flag, pointing to the server’s public certificate file. For example: curl --cacert /path/to/server.crt https://your_server.com.
    • Why it works: Option A makes the server "legitimately" trusted. Option B bypasses the trust check for this specific connection by explicitly telling curl to accept the presented certificate as valid, even though it’s not signed by a known CA.
  5. Incorrect Certificate or Private Key on the Server: The server is configured to use the wrong certificate file or the wrong private key file. This can lead to various SSL handshake failures, including certificate validation issues if the private key doesn’t match the certificate.

    • Diagnosis: On the server, verify the certificate file specified in your web server configuration (e.g., ssl_certificate in Nginx, SSLCertificateFile in Apache). Then, check the corresponding private key file (e.g., ssl_certificate_key or SSLCertificateKeyFile). You can test if a private key matches its certificate with:
      openssl x509 -noout -modulus -in /path/to/your_server.crt | openssl md5
      openssl rsa -noout -modulus -in /path/to/your_private.key | openssl md5
      
      The MD5 hashes should match.
    • Fix: Correct the paths in your web server configuration to point to the correct certificate and private key files. If they don’t match, obtain the correct private key for the certificate.
    • Why it works: The server needs to present the correct certificate and prove it possesses the corresponding private key to establish a secure connection.
  6. Expired or Revoked Certificate: The server’s certificate has passed its validity period or has been revoked by the CA.

    • Diagnosis: On the server, check the Not Before and Not After dates of the certificate: openssl x509 -in /etc/ssl/certs/your_server.crt -noout -dates. You can also check CRL (Certificate Revocation List) or OCSP (Online Certificate Status Protocol) status if your server is configured to use them.
    • Fix: Renew the server’s certificate before it expires. If it was revoked, obtain a new certificate from your CA.
    • Why it works: Certificates have a limited lifespan and can be invalidated if compromised. Using a valid, unexpired certificate is fundamental to trust.

After fixing these, the next error you’ll likely encounter is a "certificate verify failed" if you’ve only addressed the server-side configuration but not the client’s trust store.

Want structured learning?

Take the full Tls-ssl course →