Troubleshooting HTTPS
Mixed content, cert mismatch, expiry, chain errors.
Learning objectives
- Map browser errors to likely causes
- Fix mixed content, expiry, and hostname mismatch
- Use openssl and curl for certificate debugging
Symptom → cause cheat sheet
| What users see | Likely cause | First check |
|---|---|---|
| “Your connection is not private” | Expired cert, bad chain, or MITM | Expiry and chain in browser or openssl s_client |
| Certificate name mismatch | Hostname not in SAN | Compare URL to cert SANs |
| Padlock broken / mixed content | HTTPS page loads HTTP assets | Browser dev tools → Console |
| ERR_TOO_MANY_REDIRECTS | HTTP↔HTTPS loop | curl -I trace redirect chain |
| 502 Bad Gateway | PHP-FPM down or wrong socket | systemctl status php8.3-fpm |
Diagnostic commands
# Certificate presented on port 443
openssl s_client -connect www.workshopco.ca:443 -servername www.workshopco.ca < /dev/null
# Follow redirects, show headers only
curl -I -L https://www.workshopco.ca
# Check expiry dates Certbot knows about
sudo certbot certificates
Worked example — mixed content after HTTPS migration
Workshop Co. enables HTTPS but the classes page still references http://www.workshopco.ca/images/bench.jpg. Browsers block or warn because active content on an HTTPS page must also be HTTPS.
Fix: Use relative URLs (/images/bench.jpg) or https:// everywhere. Search CMS/theme for hard-coded http://. Add Content-Security-Policy: upgrade-insecure-requests as a safety net during migration.
Telling customers to “click Advanced → proceed anyway” trains bad habits. Fix the certificate or content issue instead.
Worked example — expired staging cert
staging.workshopco.ca shows expiry errors. Production is fine. Staging uses a separate cert that failed renewal because DNS pointed staging to a new IP but Certbot still ran on the old server.
Fix: Run Certbot where port 80/443 for staging actually terminates, or fix DNS. Verify with certbot renew --dry-run -d staging.workshopco.ca.
Try it yourself — triage
A colleague reports: “HTTPS works in Chrome on Mac but fails on an older Android phone with chain error.” List three things you would compare between the two clients.
Answer
- Whether the server sends the full intermediate chain (
openssl s_clientoutput) - Root/intermediate trust on older Android ( outdated CA store )
- Whether they hit a CDN vs origin with different chain config
Redirect loop puzzle
Nginx has: (1) port 80 → 301 to HTTPS; (2) port 443 if ($host = workshopco.ca) { return 301 https://www.workshopco.ca$request_uri; }; (3) load balancer also redirects HTTP to HTTPS. Users get too many redirects. What is a cleaner approach?
Answer
Use separate server blocks instead of nested if redirects. One block for apex → www on 443, one for www content. Ensure only one layer (LB or Nginx) performs HTTP→HTTPS redirect.
Quick quiz
- What is mixed content?
- Which tool shows the certificate chain from the command line?
- 502 from Nginx often means what upstream problem?
Answers
- HTTPS page loading subresources over plain HTTP.
openssl s_client- PHP-FPM or
proxy_passbackend unreachable or crashed.