How to Fix SSL Certificate Not Trusted Errors on Your Website
If you've landed here because your browser is throwing an "SSL certificate not trusted" error — or your visitors are seeing scary security warnings when they try to reach your site — you're in the right place. This guide walks you through every common cause of SSL certificate trust issues and gives you concrete steps to fix them, whether you're a site owner, developer, or systems administrator.
Why SSL Certificate Trust Errors Happen
Before diving into fixes, it helps to understand what "trusted" actually means in the context of SSL/TLS certificates.
When a browser connects to your website, it checks your SSL certificate against a list of Certificate Authorities (CAs) it already trusts — this list is built into the operating system or browser itself. If your certificate was issued by a CA that isn't on that list, or if something in the chain between your certificate and a trusted root CA is broken or missing, the browser throws a trust error.
The most common causes include:
- Missing intermediate certificates — Your server isn't sending the full certificate chain
- Expired certificate — The certificate's validity period has lapsed
- Self-signed certificate — The certificate wasn't issued by a recognized CA
- Wrong domain — The certificate doesn't match the domain the visitor is accessing
- Revoked certificate — The CA has invalidated the certificate before its expiry date
- Outdated root store — The device or OS hasn't been updated and is missing newer CA roots
- Clock skew — The server or client system clock is significantly off
Let's work through each of these systematically.
Step 1: Diagnose the Exact SSL Trust Problem
You can't fix what you haven't diagnosed. Start by inspecting your certificate properly.
Use a Browser to Read the Error Code
Different browsers give different error codes, but they all point to the underlying problem:
NET::ERR_CERT_AUTHORITY_INVALID— Chrome's way of saying the certificate isn't trustedSEC_ERROR_UNKNOWN_ISSUER— Firefox's equivalentMOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED— Policy-related trust failureERR_CERT_DATE_INVALID— Expired or not-yet-valid certificateERR_CERT_COMMON_NAME_INVALID— Domain mismatch
Click the "Not Secure" padlock icon and then "Certificate" (or equivalent in your browser) to read the full details — issuer, validity dates, and subject alternative names (SANs).
Use OpenSSL from the Command Line
For a deeper look, run this command from your terminal:
openssl s_client -connect yourdomain.com:443 -showcerts
This outputs the full certificate chain your server is sending. Look for:
- How many certificates are in the chain
- Whether the chain terminates at a recognized root CA
- Any error messages like
verify error:num=20:unable to get local issuer certificate
To check expiry specifically:
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates
Use OpDeck's SSL Certificate Checker
If you prefer a GUI-based approach, the SSL Certificate Checker gives you a clear breakdown of your certificate's validity, issuer chain, expiry date, and whether it's properly trusted. It's especially useful for quickly spotting chain issues without needing to interpret raw OpenSSL output.
Step 2: Fix a Missing or Incomplete Certificate Chain
This is the single most common cause of SSL certificate not trusted errors. Your server has your end-entity certificate installed, but it's not sending the intermediate certificates that connect it to a trusted root CA.
Why Intermediate Certificates Matter
Root CAs don't issue certificates directly to websites — they delegate to intermediate CAs, which then issue to you. Browsers trust root CAs, but they need the intermediate certificates to build the trust path. If your server doesn't include them, the browser can't verify the chain.
How to Fix It on Apache
First, get the intermediate certificate bundle from your CA. Most CAs provide this as a .ca-bundle or .crt file alongside your certificate.
In your Apache virtual host configuration:
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /path/to/your_domain.crt
SSLCertificateKeyFile /path/to/your_private.key
SSLCertificateChainFile /path/to/your_ca_bundle.crt
</VirtualHost>
After editing, test and reload:
apachectl configtest
sudo systemctl reload apache2
How to Fix It on Nginx
Nginx requires you to concatenate your certificate and the intermediate bundle into a single file:
cat your_domain.crt your_ca_bundle.crt > your_domain_chained.crt
Then update your Nginx config:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/your_domain_chained.crt;
ssl_certificate_key /path/to/your_private.key;
}
Test and reload:
nginx -t
sudo systemctl reload nginx
How to Fix It on IIS (Windows)
On IIS, you typically import the intermediate certificate into the Intermediate Certification Authorities store via the Microsoft Management Console (MMC):
- Open MMC → File → Add/Remove Snap-in → Certificates → Computer Account
- Navigate to Intermediate Certification Authorities → Certificates
- Right-click → All Tasks → Import
- Import the intermediate
.crtfile from your CA
Restart IIS after importing.
Step 3: Renew an Expired SSL Certificate
If the diagnosis shows an expired certificate, you need to renew it. The process depends on how you originally obtained the certificate.
Let's Encrypt (Certbot)
If you're using Let's Encrypt with Certbot:
sudo certbot renew
If you want to force renewal even if it's not close to expiry:
sudo certbot renew --force-renewal
Check that your auto-renewal cron job or systemd timer is working:
sudo systemctl status certbot.timer
Let's Encrypt certificates expire every 90 days, so automated renewal is critical.
Commercial CA Certificates
For paid certificates (DigiCert, Sectigo, GlobalSign, etc.):
- Generate a new CSR (Certificate Signing Request):
openssl req -new -newkey rsa:2048 -nodes \
-keyout yourdomain.key \
-out yourdomain.csr \
-subj "/C=US/ST=State/L=City/O=YourOrg/CN=yourdomain.com"
- Submit the CSR to your CA through their portal
- Complete domain validation
- Download and install the new certificate and chain files
Step 4: Replace a Self-Signed Certificate
Self-signed certificates are fine for internal development environments, but they will always trigger SSL certificate not trusted warnings in browsers because no recognized CA has vouched for them.
Get a Free Certificate from Let's Encrypt
For public-facing websites, Let's Encrypt is the easiest path to a trusted certificate:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot will automatically configure your Nginx server blocks and set up auto-renewal.
For Apache:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
Use Cloudflare's Free SSL
If your DNS is managed through Cloudflare, you can enable their Universal SSL (free) which provisions a trusted certificate automatically. This is a good option if you want to avoid managing certificate renewals manually.
Step 5: Fix a Domain Mismatch
An SSL certificate is issued for specific domain names. If the domain in the browser's address bar doesn't match any of the domains listed in the certificate's Common Name (CN) or Subject Alternative Names (SANs), you'll get a trust error.
Check Which Domains Your Certificate Covers
openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
Common mismatch scenarios:
- Certificate covers
yourdomain.combut visitor goes towww.yourdomain.com(or vice versa) - Certificate covers the old domain after a domain migration
- Wildcard certificate (
*.yourdomain.com) doesn't cover the apex domain (yourdomain.com)
Solutions
- Add a redirect: Redirect all traffic to the exact domain your certificate covers
- Reissue the certificate: Add the missing domain as a SAN — most CAs let you reissue at no extra cost
- Use a wildcard certificate: Covers all subdomains of a domain (e.g.,
*.yourdomain.com) - Use a multi-domain (SAN) certificate: Covers multiple distinct domains in a single certificate
Step 6: Handle Outdated Root Stores and Old Devices
Some older Android devices, Windows XP machines, or embedded systems have outdated root stores that don't include newer CA roots. This is particularly common with Let's Encrypt certificates, since their root (ISRG Root X1) wasn't widely trusted until relatively recently.
Cross-Signed Certificates
Let's Encrypt offers a compatibility option where certificates are cross-signed by IdenTrust's DST Root CA X3 (now expired) or via an alternative chain. When using Certbot, you can specify the preferred chain:
sudo certbot renew --preferred-chain "ISRG Root X1"
Updating the Root Store on Linux Servers
If a server itself can't verify certificates (common in server-to-server API calls):
# Debian/Ubuntu
sudo apt update && sudo apt install --reinstall ca-certificates
sudo update-ca-certificates
# RHEL/CentOS/Fedora
sudo yum update ca-certificates
Adding a Custom CA to a System Trust Store
For internal CAs used in corporate environments:
# Ubuntu/Debian
sudo cp your-internal-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# RHEL/CentOS
sudo cp your-internal-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
Step 7: Fix Clock Skew Issues
SSL certificates have strict validity windows. If your server's system clock is significantly off, it can cause certificates to appear invalid even when they're not.
Check your server's current time:
date
timedatectl status
If the time is wrong, sync with NTP:
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd
Or use ntpdate directly:
sudo ntpdate pool.ntp.org
Step 8: Check for Mixed Content Issues
Sometimes the padlock disappears or shows a warning even though your certificate is valid. This often means your HTTPS page is loading some resources (images, scripts, stylesheets) over HTTP — known as mixed content.
Identify Mixed Content
Open your browser's developer tools (F12), go to the Console tab, and reload the page. Mixed content warnings look like:
Mixed Content: The page at 'https://yourdomain.com' was loaded over HTTPS,
but requested an insecure resource 'http://yourdomain.com/image.jpg'.
Fix Mixed Content
- Update hardcoded
http://URLs in your CMS, templates, or database tohttps:// - Use protocol-relative URLs (
//yourdomain.com/resource) as a temporary fix - In WordPress, use a plugin like Better Search Replace to update URLs in the database
- Set the
Content-Security-Policy: upgrade-insecure-requestsheader to automatically upgrade HTTP requests to HTTPS
Step 9: Verify Your Fix is Working
After making changes, don't just check in one browser. Verify thoroughly.
Test with curl
curl -vI https://yourdomain.com 2>&1 | grep -E "(SSL|TLS|certificate|issuer|expire)"
A clean output will show the handshake completing without errors.
Test the Full Chain
Use the SSL Certificate Checker to confirm the full chain is valid, the certificate is trusted, and the expiry date is correct. This tool checks from an external perspective, which is what your visitors actually see — not what your local machine sees.
Test from Multiple Locations and Devices
- Use a mobile device on cellular data (not your local network)
- Test in Chrome, Firefox, Safari, and Edge
- Use an online tool like SSL Labs (ssllabs.com/ssltest) for a comprehensive grade and detailed chain analysis
Preventing SSL Certificate Trust Issues in the Future
Once you've resolved the immediate problem, put systems in place to prevent it from recurring:
Set up certificate expiry monitoring — Use a monitoring service or cron job that alerts you 30, 14, and 7 days before expiry. Many uptime monitoring tools include this.
Automate renewal — If you're using Let's Encrypt, verify your Certbot timer is running:
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
Document your certificate inventory — Keep a spreadsheet or use a secrets manager to track all certificates, their domains, expiry dates, and renewal contacts.
Test after every deployment — Any deployment that touches your web server configuration could accidentally break the certificate chain. Make SSL verification part of your post-deployment checklist.
Use HSTS — Once you're confident your HTTPS setup is solid, add HTTP Strict Transport Security headers to prevent browsers from ever falling back to HTTP:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Conclusion
Fixing an SSL certificate not trusted error comes down to correctly identifying which part of the trust chain is broken — whether that's a missing intermediate certificate, an expired cert, a domain mismatch, or an outdated root store. Work through the diagnostic steps first, then apply the targeted fix for your specific situation.
The good news is that most of these issues are straightforward to resolve once you know what you're looking at. Use the SSL Certificate Checker on OpDeck to get a quick, clear picture of your certificate's current state — it surfaces chain issues, expiry dates, and trust status in seconds, without needing to parse raw OpenSSL output. Combine that with the command-line techniques in this guide and you'll have your SSL certificate trusted and your visitors' browsers showing that green padlock in no time.
Try these tools