Why HTTPS Errors Happen After Installation

Installing an SSL certificate does not always mean HTTPS works immediately or without issues. Many server configurations, content management systems, and applications have assumptions built in that favour HTTP, and these can cause problems even after a valid certificate is in place.

Common problems include mixed content warnings, certificate chain errors, domain mismatch, expired certificates, and redirect loops. Each has a specific cause and a specific fix. Understanding what each error actually means narrows down the troubleshooting approach considerably.

If you are setting up Let's Encrypt for the first time, the auto-renewal setup guide covers how to keep certificates valid without manual intervention.

Certificate Chain Errors

A certificate chain error means the server is sending the SSL certificate but not the intermediate certificates that browsers need to verify the certificate back to a trusted root certificate authority. Browsers typically handle this gracefully by downloading missing intermediates, but some clients and older browsers fail to connect entirely.

Check the certificate chain using OpenSSL.

openssl s_client -connect yourdomain.com:443 -showcerts

This command shows all certificates in the chain. You should see the server certificate first, followed by one or more intermediate certificates, and a root certificate at the end. If the chain ends at an intermediate without a root, the root is missing from the server configuration.

For Apache, configure the certificate chain by appending the intermediate certificates to your certificate file.

cat your_domain.crt intermediate-cert.crt > bundled.crt

Update the Apache configuration to point to the bundled file.

SSLCertificateFile /etc/ssl/certs/bundled.crt
SSLCertificateKeyFile /etc/ssl/private/your_domain.key

In Nginx, use the ssl_trusted_certificate directive to provide the chain separately from the server certificate.

ssl_certificate /etc/ssl/certs/bundled.crt;
ssl_trusted_certificate /etc/ssl/certs/chain.crt;

Let's Encrypt certificates typically do not have chain issues because the chain is served correctly by default, but it is worth verifying with the OpenSSL command above after any new installation.

Mixed Content Warnings

Mixed content happens when an HTTPS page loads resources such as images, scripts, stylesheets, or iframes over HTTP. The page is technically served over HTTPS, but some of its content comes from insecure sources. Modern browsers block mixed content by default, which means parts of your page may not load, or the padlock icon may not appear.

Use the browser developer tools to identify mixed content errors. In Chrome, open DevTools with F12, go to the Console tab, and look for messages like:

Mixed Content: The page at 'https://example.com' was loaded over HTTPS,
but requested an insecure resource 'http://example.com/image.jpg'.
This request is blocked; it must be served over HTTPS.

Fix mixed content by updating all resource URLs to use HTTPS. Search your database and code for hardcoded HTTP URLs.

-- Find HTTP URLs in WordPress database
SELECT * FROM wp_posts WHERE post_content LIKE '%src="http://%';

In WordPress, use WP-CLI to replace HTTP URLs with HTTPS across the database.

wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --skip-tables=wp_options

Be careful when running search-and-replace on a live site. Test on a staging environment first, and ensure you have a current backup before making database-wide changes.

Use protocol-relative URLs as a temporary measure, but switching to explicit HTTPS is the better long-term solution.

<!-- Avoid protocol-relative URLs -->
<script src="//cdn.example.com/script.js"></script>

<!-- Use explicit HTTPS -->
<script src="https://cdn.example.com/script.js"></script>

If you use external scripts or CDN resources, verify they support HTTPS before linking to them.

Certificate Mismatch Errors

Certificate mismatch means the certificate's Common Name or Subject Alternative Name does not include the domain you are accessing it with. This commonly happens when you install a certificate for www.example.com but access the site at example.com, or when you access by IP address, or when a certificate was issued for a different subdomain entirely.

Check what the certificate was issued for using OpenSSL.

openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName

Make sure the output includes the exact domain you are using to access the site. If the certificate was issued for www.example.com and you access it as example.com, either install a certificate covering both or redirect one to the other.

For multiple subdomains, use a wildcard certificate or list each subdomain as a Subject Alternative Name during certificate creation.

# With Let's Encrypt, request a certificate covering both example.com and www.example.com
sudo certbot --nginx -d example.com -d www.example.com

If you are running Apache and need to configure multiple domains under one certificate, the Apache security configuration guide covers VirtualHost setup and SSL directives in more detail.

Expired Certificates

An expired certificate is exactly what it sounds like: the certificate validity period has passed and browsers refuse to connect to sites presenting it. If your site worked yesterday and shows this error today, check the certificate expiry date first.

echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates

The output shows notBefore and notAfter dates. If notAfter is in the past, the certificate has expired and needs renewal.

Let's Encrypt certificates expire after 90 days. If you installed Let's Encrypt manually without setting up auto-renewal, renew it now.

sudo certbot renew

Check that the Certbot cron job or systemd timer is active so renewals happen automatically going forward.

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

The dry-run confirms renewal works without actually issuing a new certificate. If it fails, check that your domain DNS is still pointing to the server and that port 80 is accessible.

Proper auto-renewal setup means you do not have to remember to renew certificates manually. The Let's Encrypt auto-renewal guide walks through the full process including cron jobs and systemd timers.

Redirect Loops After HTTPS Installation

A redirect loop occurs when the server redirects HTTPS to HTTP, or HTTP to HTTPS, which then redirects back, creating an infinite loop. The browser shows an error after too many redirects and the page never loads.

In Apache, check your .htaccess file for redirect rules that conflict with each other or with HTTPS enforcement in the main configuration.

# Force HTTPS in .htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

If you also have HTTPS enforcement in the VirtualHost configuration, the two rules will conflict and produce a redirect loop. Remove one or the other.

In Nginx, check for conflicting redirect rules across server blocks.

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    # Ensure this block does not redirect back to HTTP
}

WordPress sites often have this problem in the Site URL and Home settings. If these are set to HTTP when HTTPS is enabled, WordPress redirects to HTTP indefinitely.

# Check WordPress URLs in wp-config.php
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');

Update these to HTTPS and clear any caching plugins or server-level cache that may be serving stale redirects.

Wrong or Missing DH Parameters

Some older clients require Diffie-Hellman parameters for the SSL handshake. If you see errors like no shared cipher or dh key too small, generate new DH parameters and ensure your server is configured to use them.

sudo openssl dhparam -out /etc/ssl/private/dhparams.pem 2048

Generating DH parameters can take a few minutes on slower hardware. Once complete, reference the file in your Nginx configuration.

ssl_dhparam /etc/ssl/private/dhparams.pem;

In Apache, add the DH parameters to your SSL configuration.

SSLOpenSSLConfCmd DHParameters "/etc/ssl/private/dhparams.pem"

Using 2048-bit DH parameters is a reasonable minimum for most setups. If you are supporting very old clients that require smaller parameters, be aware that shorter DH keys reduce the effective security of the connection.

Certificate Works but Padlock Shows as Insecure

Even with a valid certificate, the padlock may show as not fully secure if there are issues with the certificate chain, mixed content, or missing security headers. Use a diagnostic tool to check any HTTPS-related issues on a specific URL.

These tools check certificate validity, chain completeness, mixed content, and redirect issues. Run them on your key pages after any HTTPS configuration change to confirm everything is working correctly.

Beyond the padlock itself, it is worth reviewing your server's security headers. Adding Strict-Transport-Security, Content-Security-Policy, and X-Content-Type-Options headers reinforces HTTPS and reduces the risk of certain attacks. The Apache security configuration guide covers header settings in more detail.

Testing Your HTTPS Configuration

After making any changes to your SSL configuration, test the result thoroughly before considering the job done. Check all major pages of your site, including those with forms, media, and third-party integrations.

Test from multiple locations and browsers if possible. Some issues appear only in specific client configurations or older browser versions.

Keep a record of what you changed and why. This makes it easier to troubleshoot future issues or roll back changes if something breaks.