The core issue is that the SSL/TLS certificate presented by the server doesn’t match the hostname the client is trying to connect to, breaking the trust chain.

Common Causes and Fixes:

  1. Incorrect server_name directive in Nginx:

    • Diagnosis: Check your Nginx configuration file (e.g., /etc/nginx/nginx.conf or files in /etc/nginx/sites-available/). Look for server blocks. Within a server block, you’ll find a listen directive and a server_name directive. For example:
      server {
          listen 443 ssl;
          server_name example.com www.example.com; # This is the key line
      
          ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
          # ... other ssl settings
      }
      
      If the server_name doesn’t include www.example.com but you’re accessing https://www.example.com, you’ll get a mismatch.
    • Fix: Add the missing hostname to the server_name directive.
      server {
          listen 443 ssl;
          server_name example.com www.example.com; # Ensure all expected hostnames are here
          # ...
      }
      
      Then reload Nginx: sudo systemctl reload nginx.
    • Why it works: Nginx uses the server_name directive to determine which server block to use for an incoming request. If the requested hostname isn’t listed, it falls back to a default or a mismatch occurs.
  2. Wildcard Certificate Not Covering Subdomain:

    • Diagnosis: If you’re using a wildcard certificate (e.g., *.example.com), it will only cover direct subdomains (like app.example.com, mail.example.com) but not the base domain (example.com) or multi-level subdomains (test.app.example.com). Check your certificate’s Subject Alternative Name (SAN) field. You can do this with openssl x509 -in /path/to/your/certificate.pem -noout -text. Look for DNS:*.example.com.
    • Fix: Either add the base domain (example.com) and any specific subdomains to your certificate request (if your CA supports it and you have a multi-domain certificate), or ensure your wildcard certificate is configured correctly in your web server. For Let’s Encrypt, you’d typically request example.com and *.example.com together.
      • Let’s Encrypt Example (Certbot): If you used Certbot, you might need to re-run it and select the correct domain names. For example, if you initially only got *.example.com and now need example.com too:
        sudo certbot --nginx -d example.com -d *.example.com
        
        This will update your Nginx configuration and renew the certificate to include both.
    • Why it works: Wildcard certificates have specific rules about what they match. Explicitly including the base domain or ensuring the wildcard covers the correct level of subdomains is crucial.
  3. IP Address Access Instead of Hostname:

    • Diagnosis: Users are trying to access the server using its IP address (e.g., https://192.168.1.100) when the certificate is issued for a hostname (e.g., example.com). Browsers will reject this because the IP address is not listed in the certificate’s SANs.
    • Fix: Instruct users to access the server using the configured hostname (e.g., https://example.com). If you must allow IP access with SSL, you’ll need to obtain a certificate that includes the IP address in its SANs, or set up a separate server block for IP access (though this is generally discouraged and often requires a self-signed certificate or a specific IP-address-based certificate from a CA).
    • Why it works: SSL/TLS relies on matching names. An IP address is not a name, and certificates are issued to names.
  4. Multiple server Blocks with Identical server_name or No server_name:

    • Diagnosis: In Nginx, if multiple server blocks listen on the same IP address and port, and they have identical server_name directives (e.g., two blocks both saying server_name example.com;), or if one has a server_name and another has no server_name (acting as a default), Nginx might pick the wrong one for a specific request. You can check for duplicate or conflicting server_name entries.
    • Fix: Ensure each server block that handles SSL has a unique server_name directive that accurately reflects the hostname it’s supposed to serve. If a block is intended as a default, it should be the only block without a specific server_name for that IP/port combination.
      # Corrected example
      server {
          listen 443 ssl;
          server_name example.com; # Specific for example.com
          ssl_certificate ...;
          # ...
      }
      
      server {
          listen 443 ssl;
          server_name www.example.com; # Specific for www.example.com
          ssl_certificate ...;
          # ...
      }
      
      Reload Nginx: sudo systemctl reload nginx.
    • Why it works: Nginx needs a clear, unambiguous way to route incoming requests to the correct virtual host configuration. Conflicting server_name directives create this ambiguity.
  5. Stale/Cached Certificate or Configuration:

    • Diagnosis: You’ve recently updated your certificate or Nginx configuration, but clients are still seeing the old one. This can happen if clients have cached the old certificate/session, or if Nginx wasn’t reloaded/restarted properly after changes. Use curl -vI https://example.com and look for the Server certificate: section to see which certificate is being presented.
    • Fix:
      • Reload Nginx: Ensure you’ve reloaded or restarted your web server after making changes. For Nginx: sudo systemctl reload nginx.
      • Clear Browser Cache: Ask users to clear their browser’s cache or try an incognito/private browsing window.
      • Check HSTS: If HTTP Strict Transport Security (HSTS) is enabled, browsers will enforce HTTPS and might stubbornly stick to a previously known secure connection. This is less about certificate mismatch and more about connection policy, but can be mistaken for it.
    • Why it works: Changes to certificates or configurations only take effect once the web server is signaled to re-read them, and clients need to establish new connections to receive them.
  6. Certificate Issued for Wrong Domain/Subdomain:

    • Diagnosis: The certificate was generated or renewed for oldexample.com or dev.example.com but you are trying to access example.com. Verify the Subject and Subject Alternative Name (SAN) fields of your certificate using openssl x509 -in /path/to/your/certificate.pem -noout -text.
    • Fix: Obtain a new certificate that correctly lists all the hostnames you intend to use. For Let’s Encrypt, this means running Certbot again with the correct domain names specified.
      sudo certbot --nginx -d example.com -d www.example.com # Or your specific domains
      
      Then reload Nginx: sudo systemctl reload nginx.
    • Why it works: The certificate must explicitly name or cover the hostname a client is trying to reach for the handshake to succeed.

The next error you’ll likely hit if you fix hostname mismatches is related to cipher suite compatibility or protocol version negotiation if your SSL configuration is also outdated.

Want structured learning?

Take the full Http course →