Skip to main content
Back to Blog

Fix SSL Certificate Chain Errors: Nginx, Apache & Troubleshooting Guide

CertWatch Team|10 min read|
SSLTLSDevOpsTroubleshootingCertificate ManagementNginxApache
Share:
Fix SSL Certificate Chain Errors: Nginx, Apache & Troubleshooting Guide

TL;DR: Certificate chain issues happen when your server doesn't send the complete chain of certificates needed to verify trust. The fix is usually simple: concatenate your certificate with the intermediate certificate(s) from your CA. This guide covers how to diagnose the problem and fix it for Nginx, Apache, Let's Encrypt, and other servers.


Related: If you're dealing with expired certificates instead of chain issues, check out our SSL Certificate Expiration Guide.


Quick Symptoms Check

You likely have a certificate chain issue if:

  • ✅ Site works in Chrome/Firefox
  • curl fails with SSL errors
  • ❌ API clients can't connect
  • ❌ Mobile apps show certificate warnings
  • ❌ SSL Labs shows "Chain Incomplete"

If this sounds familiar, you're in the right place.


The Confusing Part About Chain Errors

Here's a scenario that frustrates every DevOps engineer at some point:

Your website works fine in Chrome. No warnings, green padlock, everything looks secure. But then:

  • Your API clients start failing with SSL errors
  • curl refuses to connect
  • Automated health checks report certificate problems
  • Mobile apps on certain devices show trust errors

The certificate isn't expired. The domain matches. So what's going on?

The answer is almost always: incomplete certificate chain.


What is a Certificate Chain?

When a browser or client connects to your server over HTTPS, it needs to verify that your certificate can be trusted. This verification follows a chain of trust:

Root CA (Trusted by OS/Browser)
    ↓
Intermediate CA (Signed by Root)
    ↓
Your Certificate (Signed by Intermediate)

Why Intermediates Exist

Certificate Authorities don't sign end-entity certificates directly with their root certificate. Instead, they use intermediate certificates because:

  • Security: If a root key is compromised, it's catastrophic. Keeping it offline and using intermediates limits exposure.
  • Flexibility: CAs can issue different intermediates for different purposes or validity periods.
  • Revocation: Revoking an intermediate is easier than revoking a root.

The Problem

Your server needs to send the complete chain (your certificate + intermediates) to clients. Root certificates are already trusted by operating systems and browsers, so you don't send those. But if you only send your certificate without the intermediates, clients can't verify the chain.


Common Certificate Chain Errors

ErrorSymptomsCommon Cause
Incomplete chainWorks in browser, fails in curl/API clientsMissing intermediate certificate
Wrong orderNginx fails to start with key mismatch errorCertificates concatenated in wrong order
Expired intermediateIntermittent failures, some clients workOld intermediate not updated during renewal
Self-signed in chainTrust errors everywhereDevelopment cert accidentally deployed
Mismatched certificatesTLS handshake failuresWrong intermediate for your certificate

Why It Works in Browsers But Fails Elsewhere

This is the most confusing part of chain issues. Your site loads fine in Chrome, but curl fails. Why?

AIA Fetching

Modern browsers implement Authority Information Access (AIA) fetching. When they encounter a certificate without the full chain, they look at the AIA extension in your certificate, download the missing intermediate, and complete the chain themselves.

Browser Caching

Browsers also cache intermediate certificates. If you've ever visited a site that properly served the intermediate, your browser remembers it. So even if another site doesn't serve it, the browser already has it cached.

Why You Can't Rely on This

Here's the problem:

  • curl, wget, and most HTTP libraries don't do AIA fetching
  • API clients and backend services don't do AIA fetching
  • Some mobile browsers don't do AIA fetching
  • Fresh browser installs might not have cached intermediates
  • Automated monitoring tools will report failures

Bottom line: Your server must send the complete chain. Don't rely on browser workarounds.


How to Diagnose Chain Issues

Method 1: Online SSL Checker (Fastest)

Use our free SSL Certificate Checker to instantly see:

  • Whether your certificate chain is complete
  • Which intermediate certificates are being served
  • Any chain validation errors

This is the quickest way to diagnose the problem without command-line tools.

Method 2: OpenSSL Command Line

For a detailed look at what your server is sending:

openssl s_client -connect yourdomain.com:443 -showcerts

Look for the certificate chain in the output. You should see multiple certificates:

Certificate chain
 0 s:CN = yourdomain.com
   i:CN = R3, O = Let's Encrypt
 1 s:CN = R3, O = Let's Encrypt
   i:CN = ISRG Root X1, O = Internet Security Research Group

If you only see certificate 0 (your cert), the chain is incomplete.

Method 3: SSL Labs Test

For comprehensive analysis, use SSL Labs Server Test. It provides:

  • Detailed chain analysis
  • Trust status across different platforms
  • Overall security grade
  • Specific recommendations

Look for "Chain issues" in the results. Common messages include:

  • "Contains anchor" (you're sending the root, which is unnecessary but not harmful)
  • "Incomplete" (missing intermediate)
  • "Extra certs" (extra certificates that aren't part of the chain)

How to Fix Certificate Chain Issues

Fix: Missing Intermediate Certificate

This is the most common issue. You need to get the intermediate certificate(s) from your CA and configure your server to send them.

Where to get intermediate certificates:

  1. Your CA's documentation or downloads page
  2. The email/portal where you received your certificate
  3. What's My Chain Cert - paste your cert, get the full chain

Fix for Nginx

Nginx requires a single file containing your certificate followed by the intermediate(s):

# Concatenate your cert with the intermediate
cat your-certificate.crt intermediate.crt > combined.crt

Important: Your certificate must come first, then the intermediate(s).

Update your Nginx config:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/nginx/ssl/combined.crt;
    ssl_certificate_key /etc/nginx/ssl/your-private.key;

    # ... rest of config
}

Reload Nginx:

sudo nginx -t && sudo systemctl reload nginx

Fix for Apache

Apache uses separate directives for the certificate and chain:

<VirtualHost *:443>
    ServerName yourdomain.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-certificate.crt
    SSLCertificateChainFile /etc/ssl/certs/intermediate.crt
    SSLCertificateKeyFile /etc/ssl/private/your-private.key

    # ... rest of config
</VirtualHost>

Restart Apache:

sudo apachectl configtest && sudo systemctl restart apache2

Fix for Let's Encrypt / Certbot

Certbot usually handles the chain automatically, but issues can occur if you're using the wrong file. Here's what Certbot generates:

ls /etc/letsencrypt/live/yourdomain.com/
# cert.pem      - Your certificate only (INCOMPLETE!)
# chain.pem     - Intermediate certificate(s) only
# fullchain.pem - Your cert + intermediates (USE THIS!)
# privkey.pem   - Your private key

Common mistake: Using cert.pem instead of fullchain.pem.

Nginx with Let's Encrypt:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    # Use fullchain.pem, NOT cert.pem
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # ... rest of config
}

Apache with Let's Encrypt:

<VirtualHost *:443>
    ServerName yourdomain.com

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem

    # ... rest of config
</VirtualHost>

If you're using Certbot's --nginx or --apache plugins, it should configure this correctly. If you're having chain issues with Let's Encrypt, double-check you're referencing fullchain.pem.

Fix: Wrong Certificate Order

If Nginx fails to start with an error like:

SSL_CTX_use_PrivateKey_file failed
(SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)

You likely concatenated the certificates in the wrong order. The correct order is:

  1. Your server certificate (leaf)
  2. Intermediate certificate(s)
  3. (Never include the root)

Rebuild the combined file:

# Correct order: your cert first, then intermediate
cat your-certificate.crt intermediate.crt > combined.crt

# NOT this (wrong order):
# cat intermediate.crt your-certificate.crt > combined.crt

Fix: Expired Intermediate Certificate

If your intermediate has expired:

  1. Download the current intermediate from your CA
  2. Check the expiration: openssl x509 -in intermediate.crt -noout -dates
  3. Replace the old intermediate and rebuild your chain file
  4. Reload your web server

Fix: Multiple Intermediates

Some CAs use multiple intermediates (a chain of intermediates). In this case, concatenate them in order from your cert up to (but not including) the root:

cat your-cert.crt intermediate1.crt intermediate2.crt > combined.crt

The order should follow the chain: your cert → intermediate that signed your cert → intermediate that signed that intermediate → etc.


Verification After Fixing

After making changes, verify the fix:

Quick Test with curl

curl -v https://yourdomain.com 2>&1 | grep -A5 "Server certificate"

If curl connects without SSL errors, you're good.

Verify with OpenSSL

openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null | grep -E "^( [0-9]|Certificate chain)"

You should see multiple certificates in the chain.

Re-run SSL Checker

Run our SSL Certificate Checker again to confirm the chain is now complete.


Prevention: Avoiding Chain Issues

1. Always Install the Full Chain

When you receive a certificate from your CA, they typically provide:

  • Your certificate
  • Intermediate certificate(s) or a "CA Bundle"

Always install both, even if things seem to work without it.

2. Automate Certificate Management

Tools like cert-manager (Kubernetes), AWS Certificate Manager, or Let's Encrypt's certbot handle chain management automatically. Less manual intervention means fewer mistakes.

3. Test After Every Renewal

Certificate renewals can introduce chain issues if:

  • The CA changed their intermediate
  • Automation only renewed the cert but not the chain file
  • Manual steps were missed

Add SSL validation to your deployment pipeline or post-renewal hooks.

4. Monitor Your Certificates

Don't wait for users to report problems. Use monitoring to catch issues before they impact production.

CertWatch can monitor your certificates and alert you to chain validation failures, expiring certificates, and other issues before they cause outages.


Quick Reference Commands

Check certificate chain

openssl s_client -connect example.com:443 -showcerts

View certificate details

openssl x509 -in certificate.crt -text -noout

Verify certificate matches private key

# These should output the same hash
openssl x509 -noout -modulus -in certificate.crt | openssl md5
openssl rsa -noout -modulus -in private.key | openssl md5

Concatenate certificates for Nginx

cat your-cert.crt intermediate.crt > combined.crt

Test with curl (verbose SSL)

curl -vI https://example.com 2>&1 | grep -E "(SSL|certificate)"

Key Takeaways

  1. Chain issues are the most common SSL problem after expiration—and they're easy to miss because browsers work around them
  2. Always serve the complete chain: your certificate + intermediate(s)
  3. Order matters for Nginx: your cert first, then intermediate(s)
  4. Don't rely on browser behavior—test with curl, OpenSSL, or online checkers
  5. Automate and monitor to catch issues before they affect users

Need Help?

If you're still stuck with certificate chain issues or want to discuss SSL configuration, join our community:


Sources

  1. Cloudways - How to Fix Incomplete Certificate Chain Warning
  2. Svix Blog - Incomplete TLS Certificate Chains and How to Fix Them
  3. NGINX Documentation - Configuring HTTPS Servers
  4. SSL Labs - SSL Server Test
  5. What's My Chain Cert

Never Let a Certificate Expire Again

Monitor your SSL certificates with CertWatch. Get alerts before they expire, validate certificate chains, and keep your services running smoothly.

Share: