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.
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:
mod_sslNot Enabled or Misconfigured: The Apache SSL module (mod_ssl) is either not enabled, or the virtual host configured for port 443 lacks theSSLEngine Ondirective, preventing Apache from initiating the SSL handshake.- 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. - Conflicting
ListenDirectives: DuplicateListen 443directives inports.confor other configuration files, especially if one is implicitly or explicitly configured for HTTP and takes precedence over the SSL-enabled one. - Incorrect
SSLCertificateFile/SSLCertificateKeyFilePaths or Permissions: If Apache cannot find or read the specified SSL certificate or key files,mod_sslmight fail to initialize correctly for the virtual host, potentially causing Apache to revert to serving HTTP on that port or an alternative configured default. - 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 443directive and that it's ideally within theIfModule mod_ssl.cblock, signifying its intent for SSL. Remove any conflictingListen 443outside 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 Onand 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
SSLCertificateFileandSSLCertificateKeyFilepoint to the correct, existing files. - Permissions: The private key file (
.key) typically needs strict permissions (e.g.,600or400) and should be owned byroot: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.pemor.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 configtestreports 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.
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.