SSL Certificate Errors: "Not Secure", Mixed Content, Expired Certificates and OCSP Problems
A "Not Secure" warning means the browser does not fully trust the HTTPS connection. The cause is one of four things: the certificate has expired, it was issued for a different hostname, it was signed by an issuer the browser cannot verify (often a missing intermediate certificate), or the certificate is fine but the page loads images, scripts or styles over plain http:// (mixed content). To fix it, identify which of the four applies, reissue or renew the certificate (AutoSSL on cPanel, certbot on a VPS), make sure the web server serves the new certificate with its full chain, and change http:// links to https://.
This guide applies to shared cPanel hosting and Ubuntu 22.04/24.04 servers. It also covers OCSP stapling errors.
Prerequisites
- Access to cPanel for shared hosting, or root/sudo SSH access to your VPS.
- Access to the DNS zone for your domain.
- A terminal with
opensslanddig. Both are included on Ubuntu, macOS and WSL.
1. What is the browser SSL warning actually telling you?
Click the warning icon in the address bar, or read the error code on the warning page:
- Expired:
NET::ERR_CERT_DATE_INVALID(Chrome) orSEC_ERROR_EXPIRED_CERTIFICATE(Firefox). Renewal failed, or the server is still serving the old file. Also check that the visitor's computer clock is correct. - Wrong name:
NET::ERR_CERT_COMMON_NAME_INVALIDorSSL_ERROR_BAD_CERT_DOMAIN. The certificate does not list this hostname. A common case is a certificate that coversexample.combut notwww.example.com. - Untrusted issuer:
NET::ERR_CERT_AUTHORITY_INVALIDorSEC_ERROR_UNKNOWN_ISSUER. The certificate is self-signed, or the intermediate chain is missing. - Mixed content: there is no error page, but the padlock is missing or shows "Not secure". The browser console (F12) shows
Mixed Content: The page at ... was loaded over HTTPS, but requested an insecure resource.
2. Why is AutoSSL not issuing a certificate in cPanel?
AutoSSL proves you control the domain by requesting a file under /.well-known/ over HTTP. Validation fails if that request does not reach your hosting account.
Check that DNS points to your hosting server
Run these lookups and compare the results with the server IP shown in cPanel under General Information:
dig +short example.com A
dig +short www.example.com A
dig +short example.com AAAA
dig +short example.com CAA
Check each result:
- If
wwwreturns nothing, add an A record or a CNAME record forwww. - If an AAAA record points to a different server, delete it or correct it.
- If a CAA record exists, it must allow the CA that issues your certificate, for example
sectigo.comorletsencrypt.org.
Make sure .htaccess does not block validation
Validation fails if .htaccess rules redirect requests to another domain or a maintenance page, or deny access. Exempt the validation paths in public_html/.htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Re-run AutoSSL
- Open cPanel » Security » SSL/TLS Status and click Run AutoSSL.
- When it finishes, check the status next to each domain. The failure reason, such as a DNS mismatch, is shown there.
Resellers can also use WHM » SSL/TLS » Manage AutoSSL. Use the Manage Users tab to run a check for a single account, and the Logs tab to see detailed errors.
After the certificate is issued, you can turn on Force HTTPS Redirect under cPanel » Domains » Domains.
3. Why did my Let's Encrypt certificate expire on a VPS?
See what the server is really serving
This command shows the certificate visitors receive, not just the files on disk:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
Check certbot and its renewal timer
sudo certbot certificates
systemctl list-timers | grep -i certbot
sudo certbot renew --dry-run
If the dry run fails, read /var/log/letsencrypt/letsencrypt.log. Then check which authenticator the renewal uses in /etc/letsencrypt/renewal/example.com.conf. Typical failures:
- Port 80 is closed. Open it with
sudo ufw allow 80/tcp. - The
standaloneauthenticator collides with Nginx or Apache, because both need port 80. Reissue withsudo certbot --nginx -d example.com -d www.example.com(or--apache) so renewals work while the web server runs.
Confirm Nginx or Apache points to the live files
sudo grep -R "ssl_certificate" /etc/nginx/
sudo grep -Ri "SSLCertificate" /etc/apache2/sites-enabled/
The paths should use the live symlinks, as below. Paths into /etc/letsencrypt/archive/, or to a manually copied file in /etc/ssl/, never update when the certificate renews.
# Nginx
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Apache
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Reload the web server after every renewal
Nginx and Apache keep the old certificate in memory until they are reloaded. This deploy hook reloads Nginx automatically after each successful renewal:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-web.sh > /dev/null <<'EOF'
#!/bin/sh
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-web.sh
sudo nginx -t && sudo systemctl reload nginx
For Apache, replace the reload line with systemctl reload apache2, and test the configuration with sudo apache2ctl configtest.
4. How do I fix mixed content warnings?
For WordPress, work through these steps:
- Set both WordPress Address and Site Address to
https://under Settings » General. - Replace the stored
http://URLs in the database with WP-CLI. The first command is a dry run that only reports what would change:cd ~/public_html wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run wp search-replace 'http://example.com' 'https://example.com' --all-tables wp cache flush - Check theme files, custom HTML and CDN settings for any hard-coded
http://links.
For non-WordPress sites, send this header to make browsers upgrade the remaining requests automatically:
Header always set Content-Security-Policy "upgrade-insecure-requests"
This is the Apache/LiteSpeed form. In Nginx, use add_header Content-Security-Policy "upgrade-insecure-requests" always; instead.
5. What does "OCSP validation failed" mean?
With OCSP stapling, your server fetches a signed "not revoked" response from the CA and attaches it to the TLS handshake. Errors usually have one of these causes:
- Outbound traffic is blocked. A firewall stops the server from reaching the CA's OCSP responder on port 80.
- Nginx has no resolver. Without a
resolverdirective, Nginx cannot look up the responder's hostname. - The response is stale. An old response is still cached after you replaced the certificate.
- The chain is wrong. The intermediate certificate is missing or incorrect, so the stapled response cannot be verified.
Check whether the certificate has an OCSP URL, whether the server can reach it, and whether a response is being stapled:
sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -ocsp_uri
curl -sI http://ocsp.example-ca.com # use the URL printed above
echo | openssl s_client -connect example.com:443 -servername example.com -status 2>/dev/null | grep -A3 "OCSP response"
A correct Nginx stapling configuration looks like this:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
Restart Nginx with sudo systemctl restart nginx to clear the stapling cache.
6. How do I test my SSL setup with SSL Labs?
Enter your domain at https://www.ssllabs.com/ssltest/. Look for these findings:
- "Chain issues: Incomplete": serve
fullchain.peminstead ofcert.pem. - "Certificate name mismatch": reissue the certificate with every hostname included.
- The OCSP stapling result: confirms whether the step 5 configuration works.
Grade A or A+ means the setup is correct.
Verify it works
- Open the site in a private window and confirm the padlock appears on
https://example.comandhttps://www.example.com. - Re-run the
openssl s_clientcommand from step 3 and confirmnotAfteris in the future and every hostname is listed. - Open the browser console (F12) and confirm there are no "Mixed Content" messages.
- On a VPS, confirm
sudo certbot renew --dry-runreports success.
Common problems
- Certbot shows a renewed certificate, but browsers still see the expired one → The web server was not reloaded, or its configuration points to
archive/or a copied file. Fix the paths and reload. - AutoSSL says "DNS does not resolve to this server" → Correct the A or AAAA records, wait for propagation, then click Run AutoSSL again.
- The certificate is valid on
example.combut shows an error onwww→ Add thewwwDNS record and reissue. On a VPS, include-d www.example.com. - Some browsers show an untrusted certificate while others do not → The intermediate chain is missing. Serve
fullchain.pem. - A redirect loop appears after forcing HTTPS behind a proxy or CDN → Set the CDN to full/strict SSL mode, and remove any duplicate redirect rules.
Frequently asked questions
How long does AutoSSL take to issue a certificate?
Usually a few minutes after you click Run AutoSSL, as long as DNS already points to the server. If DNS has just changed, allow time for propagation first.
Can I use my own paid certificate instead of AutoSSL?
Yes. Install it under cPanel » Security » SSL/TLS » Manage SSL sites, including the CA bundle. AutoSSL will not replace a valid certificate you installed yourself.
Do I need OCSP stapling?
No. Stapling is optional and has no effect on Let's Encrypt certificates. If it causes errors, turning it off is a safe fix.
Need help? If the certificate still fails after these steps, open a support ticket. Include your domain and the exact browser error or log output.