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:
-
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
curlclient 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.crtor/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
.crtfile in/usr/local/share/ca-certificates/and then runsudo 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.
- Diagnosis: On the server, run
-
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.pemorchained.crt. For example, if your server cert isyour_server.crtand the intermediate isintermediate.crt, the file would be:
Then, configure your web server (e.g., Nginxcat your_server.crt intermediate.crt > fullchain.pemssl_certificate) or application to use thisfullchain.peminstead of justyour_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.
- Diagnosis: Use
-
Client is Using an Outdated CA Bundle: Your operating system or
curlinstallation 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.crton 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. Forcurlspecifically on some systems, you might need to explicitly tell it where to find the CA bundle using the--cacertoption, 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.
- Diagnosis: Check the modification date of your system’s CA bundle file (e.g.,
-
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
curlto trust this specific self-signed certificate using the--cacertflag, 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
curlto accept the presented certificate as valid, even though it’s not signed by a known CA.
-
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_certificatein Nginx,SSLCertificateFilein Apache). Then, check the corresponding private key file (e.g.,ssl_certificate_keyorSSLCertificateKeyFile). You can test if a private key matches its certificate with:
The MD5 hashes should match.openssl x509 -noout -modulus -in /path/to/your_server.crt | openssl md5 openssl rsa -noout -modulus -in /path/to/your_private.key | openssl md5 - 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.
- Diagnosis: On the server, verify the certificate file specified in your web server configuration (e.g.,
-
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 BeforeandNot Afterdates 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.
- Diagnosis: On the server, check the
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.