HAProxy is terminating TLS connections and then forwarding the decrypted HTTP traffic to your backend servers.

The Problem: TLS Handshake Failures

HAProxy is failing to establish a TLS connection with the client, meaning your users can’t reach your service. This happens because HAProxy can’t complete the handshake process, which involves exchanging certificates and agreeing on encryption parameters.

Common Causes and Fixes

  1. Expired Certificate:

    • Diagnosis:
      openssl x509 -in /etc/ssl/certs/your_domain.crt -noout -dates
      
      Look for notBefore and notAfter dates. If notAfter is in the past, the certificate is expired.
    • Fix: Obtain a new certificate from your Certificate Authority (CA) and replace the existing files (e.g., your_domain.crt, your_domain.key).
      # Example: Replace old files with new ones
      mv /etc/ssl/certs/your_domain.crt /etc/ssl/certs/your_domain.crt.old
      mv /etc/ssl/certs/your_domain.key /etc/ssl/certs/your_domain.key.old
      cp /path/to/new/your_domain.crt /etc/ssl/certs/your_domain.crt
      cp /path/to/new/your_domain.key /etc/ssl/certs/your_domain.key
      chmod 600 /etc/ssl/certs/your_domain.key
      
    • Why it works: The client’s browser or tool explicitly checks the validity period of the certificate. An expired certificate is untrustworthy, and the handshake will fail immediately.
  2. Incorrect Certificate/Key Pair:

    • Diagnosis: HAProxy logs might show errors like SSL handshake failed or certificate verification failed. Manually check if the private key matches the certificate.
      openssl x509 -noout -modulus -in /etc/ssl/certs/your_domain.crt | openssl md5
      openssl rsa -noout -modulus -in /etc/ssl/certs/your_domain.key | openssl md5
      
      The MD5 hashes should match.
    • Fix: Ensure the crt and key files specified in your HAProxy configuration (crt directive) are the correct, corresponding pair.
      frontend http_frontend
          bind *:443 ssl crt /etc/ssl/certs/your_domain.crt
          # ... other frontend config
      
      If they don’t match, correct the crt and key paths or replace them with the correct files.
    • Why it works: The server must prove it possesses the private key corresponding to the public key in the certificate. If they don’t match, the server can’t perform the necessary cryptographic operations to authenticate itself.
  3. Missing Intermediate Certificates (Chain Issues):

    • Diagnosis: Clients might report "certificate chain is incomplete" or similar errors. A manual check with openssl s_client can reveal this.
      openssl s_client -connect your_domain.com:443 -servername your_domain.com < /dev/null
      
      Examine the Certificate chain section. If it only shows your server certificate and not the CA’s intermediate certificates, there’s a problem.
    • Fix: Concatenate your server certificate with its intermediate certificates into a single file, ordered correctly (server cert first, then intermediates).
      cat your_domain.crt intermediate_ca.crt > your_domain_fullchain.crt
      
      Update your HAProxy configuration to point to this new your_domain_fullchain.crt file.
      frontend http_frontend
          bind *:443 ssl crt /etc/ssl/certs/your_domain_fullchain.crt
          # ...
      
    • Why it works: Browsers and clients need to trust the entire chain of certificates back to a trusted root CA. If intermediates are missing, the client can’t verify the authenticity of your server certificate.
  4. Incorrect Permissions on Certificate/Key Files:

    • Diagnosis: HAProxy logs will often show errors like permission denied or cannot open file.
    • Fix: Ensure the HAProxy process (usually running as user haproxy or nginx) has read permissions on both the certificate and private key files. The private key should ideally only be readable by the HAProxy user.
      chown haproxy:haproxy /etc/ssl/certs/your_domain.crt
      chown haproxy:haproxy /etc/ssl/certs/your_domain.key
      chmod 640 /etc/ssl/certs/your_domain.key # Only readable by owner and group
      chmod 644 /etc/ssl/certs/your_domain.crt # Readable by all
      
    • Why it works: HAProxy needs to read the certificate and private key to perform the TLS handshake. If it lacks the necessary permissions, it cannot access these critical files.
  5. Incorrect SSL Configuration in HAProxy:

    • Diagnosis: Generic SSL handshake failed errors in HAProxy logs, especially after configuration changes.
    • Fix: Review your bind line for SSL/TLS. Ensure the ssl keyword is present and the crt path is correct. Check for typos or incorrect directives.
      frontend http_frontend
          bind *:443 ssl crt /etc/ssl/certs/your_domain.crt ca-file /etc/ssl/certs/ca-bundle.crt
          mode http
          default_backend http_backend
      
      If you’re using client certificates (ca-file or verify required), ensure those files are also correctly specified and accessible.
    • Why it works: The bind directive is how HAProxy listens for incoming connections and what protocols it expects. An improperly configured bind line will prevent HAProxy from correctly initiating or responding to TLS connections.
  6. Protocol/Cipher Mismatch:

    • Diagnosis: HAProxy logs might indicate "unsupported protocol" or "no common cipher." Clients might report "unsupported_cipher_suite."
    • Fix: Configure HAProxy to support modern TLS versions and a secure set of ciphers. Use ssl-default-bind-ciphers and ssl-default-bind-options directives.
      frontend http_frontend
          bind *:443 ssl crt /etc/ssl/certs/your_domain.crt \
              ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
          ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
          mode http
          default_backend http_backend
      
    • Why it works: Both the client and the server must agree on a TLS protocol version and a cipher suite for encryption. If they don’t have any common options, the handshake fails. This ensures compatibility and security.

After resolving TLS handshake issues, you’ll likely encounter problems with HAProxy forwarding traffic to your backend servers, such as 503 Service Unavailable errors.

Want structured learning?

Take the full Haproxy course →