Web Server Advanced

Fixing Apache’s ssl_error_rx_record_too_long on Ubuntu 20.04 LTS

Resolve Apache's `ssl_error_rx_record_too_long` on Ubuntu 20.04 LTS. This guide diagnoses and fixes HTTP content served over HTTPS port 443, restoring secure connections.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Resolve Apache's `ssl_error_rx_record_too_long` on Ubuntu 20.04 LTS. This guide diagnoses and fixes HTTP content served over HTTPS port 443, restoring secure connections.

When navigating to an HTTPS-enabled website, encountering the ssl_error_rx_record_too_long error is a clear indication that your browser is expecting a secure TLS/SSL handshake but is instead receiving plain, unencrypted HTTP data. On Apache, specifically on port 443, this almost universally points to a misconfiguration where Apache is serving HTTP content on a port designated for HTTPS traffic, or it's failing to initialize SSL correctly. This guide will walk you through diagnosing and resolving this critical issue on your Ubuntu 20.04 LTS server.

Symptom & Error Signature

Users attempting to access your website via https://yourdomain.com will see a browser-specific error message. Common variations include:

Mozilla Firefox:

Secure Connection Failed

An error occurred during a connection to yourdomain.com. SSL received a record that exceeded the maximum permissible length.

Error code: SSL_ERROR_RX_RECORD_TOO_LONG

Google Chrome:

This site can't provide a secure connection
yourdomain.com sent an invalid response.
ERR_SSL_PROTOCOL_ERROR

While the browser error is the primary symptom, Apache access or error logs might not always explicitly detail this client-side SSL negotiation failure. However, you might see unusual access patterns or internal server errors if related modules are not loading correctly.

Root Cause Analysis

The ssl_error_rx_record_too_long error on Apache, particularly on port 443, stems from a fundamental mismatch in protocol expectation. The client (browser) initiates a TLS/SSL handshake, sending an encrypted ClientHello message. If the server (Apache) on port 443 responds with unencrypted HTTP data (like a standard HTTP 200 OK header or a redirect), the client's SSL/TLS engine detects a "record too long" because it's trying to interpret plain text as an encrypted record.

The most common underlying reasons for this behavior include:

  1. mod_ssl Not Enabled or Misconfigured: The Apache SSL module (mod_ssl) is either not enabled, or the virtual host configured for port 443 lacks the SSLEngine On directive, preventing Apache from initiating the SSL handshake.
  2. HTTP Virtual Host on Port 443: A standard HTTP (<VirtualHost *:443>) virtual host is configured to listen on port 443 without any SSL directives. This is the most prevalent cause. Apache will simply serve plain HTTP over port 443.
  3. Conflicting Listen Directives: Duplicate Listen 443 directives in ports.conf or other configuration files, especially if one is implicitly or explicitly configured for HTTP and takes precedence over the SSL-enabled one.
  4. Incorrect SSLCertificateFile/SSLCertificateKeyFile Paths or Permissions: If Apache cannot find or read the specified SSL certificate or key files, mod_ssl might fail to initialize correctly for the virtual host, potentially causing Apache to revert to serving HTTP on that port or an alternative configured default.
  5. Reverse Proxy Misconfiguration: If Apache is behind a reverse proxy (e.g., Nginx, HAProxy), and the proxy is configured to terminate SSL and then forward plain HTTP to Apache on port 443 (where Apache is expecting HTTPS), this mismatch can occur. However, the error signature usually points to Apache itself being the direct culprit responding with plain HTTP.

Step-by-Step Resolution

Follow these steps carefully to diagnose and resolve the ssl_error_rx_record_too_long error on your Apache server.

1. Verify mod_ssl is Enabled

The Apache SSL module (mod_ssl) is essential for handling HTTPS connections. Ensure it's enabled.

sudo a2enmod ssl
sudo systemctl restart apache2

If mod_ssl was not enabled, enabling it and restarting Apache might resolve the issue if your virtual host was correctly configured but the module was missing.

2. Inspect Apache Configuration for Port 443

The core of the problem usually lies in how Apache is configured to listen on port 443.

a. Check ports.conf

Examine /etc/apache2/ports.conf to ensure Listen 443 is present and not duplicated or conflicting with other Listen directives.

sudo nano /etc/apache2/ports.conf

You should typically see something like:

# If you add NameVirtualHost set here.
NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

Ensure there's only one active Listen 443 directive and that it's ideally within the IfModule mod_ssl.c block, signifying its intent for SSL. Remove any conflicting Listen 443 outside this block that might be intended for plain HTTP.

b. Review Virtual Host Configurations

Navigate to your Apache sites-enabled directory and examine your virtual host files, especially those listening on port 443.

ls -l /etc/apache2/sites-enabled/

Open the relevant configuration file (e.g., yourdomain-ssl.conf or default-ssl.conf):

sudo nano /etc/apache2/sites-enabled/yourdomain-ssl.conf

Look for a <VirtualHost *:443> block. It must contain SSLEngine On and directives pointing to your SSL certificate and key files.

Correct Example (HTTPS Virtual Host):

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com
    DocumentRoot /var/www/yourdomain.com/html

    ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
    CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined

    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/yourdomain.com/chain.pem # Optional, depending on cert provider

    <Directory /var/www/yourdomain.com/html>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>

    # HSTS (optional, but recommended for production)
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

    # Other SSL/TLS configuration (e.g., cipher suites, protocols)
    SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
    SSLHonorCipherOrder on

</VirtualHost>
</IfModule>

Incorrect Example (Likely Cause of Error):

<VirtualHost *:443> # This is on port 443, but no SSL directives!
    ServerName yourdomain.com
    DocumentRoot /var/www/yourdomain.com/html

    ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
    CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined

    # MISSING: SSLEngine On
    # MISSING: SSLCertificateFile
    # MISSING: SSLCertificateKeyFile
</VirtualHost>

If you find a <VirtualHost *:443> block without SSLEngine On and the SSLCertificateFile/SSLCertificateKeyFile directives, this is almost certainly the root cause. You need to either:

  • Add the SSLEngine On and certificate directives if this virtual host is intended for HTTPS.
  • Rename the port to 80 (<VirtualHost *:80>) if it's intended for plain HTTP.

Ensure you don't have a plain HTTP <VirtualHost *:443> block and a correct HTTPS <VirtualHost *:443> block simultaneously in different files. Apache might pick up the first one it parses, leading to the error. Resolve any such duplication.

3. Validate SSL Certificate and Key Paths/Permissions

Even if SSLEngine On is present, incorrect paths or permissions for your certificate and key files can prevent mod_ssl from loading.

  • Paths: Double-check that SSLCertificateFile and SSLCertificateKeyFile point to the correct, existing files.
  • Permissions: The private key file (.key) typically needs strict permissions (e.g., 600 or 400) and should be owned by root:root, but readable by the Apache user (www-data). The certificate files can be more permissive (e.g., 644).
# Example for Let's Encrypt files
ls -l /etc/letsencrypt/live/yourdomain.com/
sudo chmod 600 /etc/letsencrypt/live/yourdomain.com/privkey.pem

The private key file (privkey.pem or .key) must be securely stored and readable by Apache. Incorrect permissions are a common source of SSL initialization failures.

4. Test Apache Configuration and Restart

After making any changes to your Apache configuration files, always test for syntax errors before restarting the service.

sudo apache2ctl configtest

You should see Syntax OK. If not, address the reported errors.

Once Syntax OK is confirmed, restart Apache:

sudo systemctl restart apache2

If apache2ctl configtest reports errors, do not proceed with restarting Apache until they are resolved. A broken configuration can prevent Apache from starting at all.

5. Consider External Factors (Reverse Proxies)

If you are using a reverse proxy (like Nginx, HAProxy, or a load balancer) in front of Apache, verify its configuration.

  • If the proxy is terminating SSL, it should forward traffic to Apache on a plain HTTP port (e.g., 80 or a custom internal port) and Apache should then respond with HTTP.
  • If the proxy is merely passing through SSL traffic, Apache still needs to handle the SSL handshake correctly on port 443, as detailed in the previous steps.

This error ssl_error_rx_record_too_long strongly suggests Apache itself is serving HTTP on port 443, so focus your primary troubleshooting on Apache's direct configuration first.

By meticulously following these steps, you should be able to identify and rectify the Apache configuration causing the ssl_error_rx_record_too_long error, restoring secure HTTPS access to your website.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn →

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.