Your Connection Is Not Private (SSL): How to Diagnose and Fix
Resolve the NET::ERR_CERT_AUTHORITY_INVALID error and other SSL warnings in the browser by identifying the real cause — certificate, chain, date, or DNS.
The “Your connection is not private” warning in Chrome (or “Warning: Potential Security Risk Ahead” in Firefox) is one of the most ambiguous screens on the modern web. Behind a single friendly message, the browser hides more than fifteen distinct error codes — each pointing to a different root cause. Treating them all as the same problem leads to wrong attempts: renewing a certificate that is still valid, touching DNS when the problem is the clock, or worse, instructing the end user to click “Proceed” and expose the connection.
This guide is for those who operate their own server (VPS or bare-metal) and need to quickly identify the real problem, separate what is the server’s responsibility from what is the client’s, and apply the correct fix. The full process takes between 10 and 20 minutes, depending on the cause.
The fundamental premise: SSL errors are always specific. Before touching any configuration, you need to read the exact code the browser shows and decide on the diagnostic path.
Prerequisites
SSH access to the server (sudo or root), an updated browser (Chrome 117+ or Firefox 120+) and the command-line tools openssl, curl and dig installed. On Ubuntu/Debian: sudo apt install -y openssl curl dnsutils. Basic knowledge of how your web server is configured (nginx, Apache, or Caddy).
443 /etc/letsencrypt/live/domain/ fullchain.pem Identify the exact error code
Before touching anything, open the error page in the browser and click “Advanced” (Chrome) or “Technical details” (Firefox). You will see a code in the format NET::ERR_CERT_* or SEC_ERROR_*. That code is the starting point — each one requires different treatment.
The table below covers the most common ones:
| Code | Likely cause | Where to fix |
|---|---|---|
NET::ERR_CERT_AUTHORITY_INVALID | Untrusted CA or incomplete chain | Server |
NET::ERR_CERT_DATE_INVALID | Expired certificate or wrong clock | Server or client |
NET::ERR_CERT_COMMON_NAME_INVALID | Certificate for another domain | Server |
NET::ERR_CERT_REVOKED | Certificate revoked by the CA | Server (reissue) |
NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM | Obsolete SHA-1 algorithm | Server (reissue SHA-256+) |
SSL_ERROR_BAD_CERT_DOMAIN | Accessed domain does not match SAN | Server |
NET::ERR_SSL_PROTOCOL_ERROR | TLS handshake failed (version/cipher) | Server |
Write down the exact error code and the domain (including subdomain) where it appears. The difference between www.site.com and site.com is critical — a certificate issued for only one does not automatically cover the other.
Test on another device on the same network and on a different network (mobile 4G, for example). If the error appears on all of them, it is a server problem. If it appears on only one, it is local.
Diagnose from the server side
Use openssl s_client to see exactly what the server is presenting to the browser. This command is the technical equivalent of “opening the page” — no cache, no extensions, no ambiguity.
Connect to your domain and capture the complete chain:
openssl s_client -connect domain.com:443 \
-servername domain.com \
-showcerts < /dev/nullThe -servername flag is mandatory — without it, servers with multiple sites (SNI) may deliver the wrong certificate. The output lists each certificate served between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.
Check how many certificates appear. In a healthy configuration you see at least 2: the leaf (for your domain) and the intermediate (from the CA). If only 1 appears, the chain is incomplete — this is the most common cause of NET::ERR_CERT_AUTHORITY_INVALID on servers that “were working until last week”.
Extract the validity dates and covered domains:
echo | openssl s_client -connect domain.com:443 \
-servername domain.com 2>/dev/null | \
openssl x509 -noout -dates -subject -ext subjectAltNameYou should see notBefore and notAfter (validity), the subject (main domain), and the SAN list (Subject Alternative Names — every domain the cert covers).
Do not try to renew a certificate before confirming that the problem is validity. Renewing a certificate that is valid but has an incomplete chain solves nothing — you only swap one valid leaf for another valid leaf, keeping the real problem in place.
Fix incomplete chain issues
An incomplete chain is the most common configuration error on Linux servers. You generated the certificate, copied it to nginx, and everything seems OK — but the server is serving only the leaf, without the intermediate.
On nginx servers with Let’s Encrypt, the ssl_certificate directive must point to fullchain.pem, not cert.pem:
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;The fullchain.pem is the concatenation of the leaf + intermediate(s) in the correct order. The cert.pem contains only the leaf — using it breaks clients that do not cache the intermediate (many old Android devices, embedded systems, some corporate operating systems).
Reload the configuration without restarting:
sudo nginx -t && sudo systemctl reload nginxThe nginx -t validates the syntax before reloading — if it fails, your old configuration keeps running.
On Apache, the equivalent directive is SSLCertificateFile, and since version 2.4.8 it accepts fullchain. In older versions you need SSLCertificateChainFile pointing separately to the intermediate. Check your version with apache2 -v (Debian/Ubuntu) or httpd -v (RHEL/CentOS).
Fix date and clock issues
If the code is NET::ERR_CERT_DATE_INVALID, there are two possibilities: the certificate has actually expired (server) or the client clock is wrong (local). Differentiating is straightforward.
On the server, check the current time and the NTP service:
timedatectl statusLook for System clock synchronized: yes and NTP service: active. If either is no or inactive:
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncdVirtual servers that were suspended for a long time (restored snapshot, migration between nodes) frequently wake up with a stale clock — the valid certificate appears expired until NTP syncs.
Compare the server date with the certificate validity:
date -u
echo | openssl s_client -connect domain.com:443 \
-servername domain.com 2>/dev/null | \
openssl x509 -noout -enddateIf the current date is after notAfter, the certificate expired — renew it. If it is before notBefore, the certificate was issued for the future (rare, usually a timezone error at issuance).
Verify the fix worked
After applying the fix, validate on three layers — server, public chain, and a real browser.
Clear the browser cache and test in an incognito window. Certificate caching is aggressive: Chrome may hold an old certificate for up to 24 hours in some cases. An incognito window ignores most of that cache.
Run an external test via SSL Labs:
curl -sI https://api.ssllabs.com/api/v3/analyze?host=domain.comOr open https://www.ssllabs.com/ssltest/analyze.html?d=domain.com in the browser. You want an A or A+ grade. B/C grades indicate additional issues (weak protocols, obsolete ciphers) worth fixing even if the main error is already gone.
Validating only in Chrome on your desktop is not enough. Test on at least: Firefox (independent CA store), Safari iOS (stricter validation), and curl from the command line (curl -v https://domain.com). If all three work without warnings, your configuration is solid.
Common troubleshooting
Error only appears on www but not the root (or vice versa)
Your certificate covers only one of the two. Reissue including both names. With certbot:
sudo certbot --nginx -d domain.com -d www.domain.com
The -d flag accepts multiple domains in a single request — they all go into the same certificate via SAN.
Error after installing antivirus or corporate proxy
Antivirus software that performs TLS inspection (Kaspersky, BitDefender, ESET) installs its own CA on the machine and re-signs all HTTPS traffic. If this CA is not in the browser trust store, every site breaks. Solution: disable SSL inspection in the antivirus or accept its CA manually. On corporate networks with proxies (Zscaler, Forcepoint), the IT team needs to distribute the company CA via group policy.
Automatic renewal stopped working
Check the certbot cron and the logs:
sudo systemctl status certbot.timer
sudo journalctl -u certbot --since "30 days ago"
Common causes: port 80 blocked by the firewall (HTTP-01 challenge fails), DNS pointing to the wrong IP after a migration, or Let’s Encrypt rate limiting (5 failures per hour per domain).
Next steps
After resolving the immediate error, it is worth hardening the TLS configuration to prevent recurrence. Consider enabling HSTS (HTTP Strict Transport Security) with Strict-Transport-Security: max-age=31536000; includeSubDomains — this forces the browser to use HTTPS for a year and eliminates downgrade attacks. Monitor certificate expiration with tools like Uptime Kuma or a simple cron that fires an alert 14 days before notAfter. For sites with serious traffic, enable OCSP stapling (ssl_stapling on in nginx) — it reduces first-connection latency and decreases dependency on the CAs.
If you are putting this into production, a Hostini VPS comes with certbot pre-installed and automatic renewal already configured — you just point DNS and run the issuance command.
Frequently asked questions
Why does the error appear in some browsers but not others?
Each browser maintains its own list of trusted root certificate authorities. Chrome and Edge use the operating system store, while Firefox has its own. If the certificate was issued by a CA that Firefox knows but Windows does not, only Chrome will complain. Revocation policy also matters (Chrome respects CRLite, Firefox uses OCSP), as does support for older algorithms.
The green padlock in Chrome disappeared but the site works — is the certificate valid?
Not necessarily. Chrome 117+ removed the padlock icon from the UI by default and shows only a neutral settings icon. Click the icon and look for Connection is secure to confirm. If it shows Not secure or a yellow triangle, there is a real problem — usually mixed content (HTTPS loading an HTTP resource) or a certificate expiring in less than 7 days.
NET::ERR_CERT_AUTHORITY_INVALID on a server with Let's Encrypt working for months — what changed?
It is almost always an incomplete intermediate chain after renewal. Let's Encrypt changed the cross-root (ISRG Root X1 vs DST Root CA X3) in 2024, and old configurations that served only the leaf without the R3 intermediate broke on old Android clients and some systems. Serve fullchain.pem (not cert.pem) in the ssl_certificate directive.
The error appears on one specific machine on the network and no others — is it a server issue?
No. If a single machine sees the error while others on the same network access normally, the problem is local: clock out of sync, antivirus intercepting TLS (Kaspersky, BitDefender, ESET do this), a corporate proxy with its own CA not installed, or a browser extension interfering. Start with the clock.
How do I check the certificate chain is complete before pushing to production?
Use openssl s_client -connect domain.com:443 -servername domain.com -showcerts. The output lists every certificate served. You should see the leaf, the intermediate, and ideally the root. If only 1 certificate appears, the chain is incomplete. Tools like SSL Labs (ssllabs.com/ssltest) and testssl.sh give a more visual diagnosis and detect other issues (weak protocols, obsolete ciphers).
Can I ignore the warning and continue — is it safe?
It depends on the cause. If it is your own test server with a self-signed certificate, yes. If it is a public site you do not control, no. The warning may indicate active interception by an attacker (MITM on public Wi-Fi), a compromised CA, or phishing. Never click Continue for sites where you will enter a password, card, or sensitive data.