In this article, we will show how to solve the “400 Bad Request: The plain HTTP request was sent to HTTPS port” in Nginx HTTP server. This error normally arises when you try to configure Nginx to handle both HTTP and HTTPS requests.
For the purpose of this guide, we are considering a scenario in which nginx is serving multiple websites implemented through server blocks (or virtual hosts in Apache) only one website uses SSL and the rest do not.
Read Also: The Ultimate Guide to Secure, Harden and Improve Performance of Nginx
We will also consider the sample SSL configuration below (we have changed the actual domain name for security reasons), which tells nginx to listen to both port 80 and 443. And all requests on HTTP should to be redirected to HTTPS by default.
Nginx Sample Configuration
server{ listen 80; server_name example.com www.example.com; return 301 https://www.example.com$request_uri; } server { listen 443 ssl http2; server_name example.com www.example.com; root /var/www/html/example.com/; index index.php index.html index.htm; #charset koi8-r; access_log /var/log/nginx/example.com/example.com_access_log; error_log /var/log/nginx/example.com/example.com_error_log error; # SSL/TLS configs ssl on; ssl_certificate /etc/ssl/certs/example_com_cert_chain.crt; ssl_certificate_key /etc/ssl/private/example_com.key; include /etc/nginx/ssl.d/ssl.conf; location / { try_files $uri $uri/ /index.php?$query_string; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/html/example.com/; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root /var/www/html/example.com/; fastcgi_pass 127.0.0.1:9001; #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; include /etc/nginx/fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
Using the above configuration, once a client tries to access your site via port 80 i.e http://example.com
, the error in question will be displayed as in the following screen shot.
You encounter this error because every time a clien tries to access your site via HTTP, the request is redirected to HTTPS. It’s because the nginx expects SSL to be used in the transaction yet the original reques t(received via port 80) was plain HTTP, it complains with the error.
On the other hand, if a client uses https://example.com
, they will not encounter the above error. In addition, if you have other websites configured not to use SSL, nginx will try to use HTTPS by default for them resulting to the above error.
To fix this error, comment out the line below in your configuration or set it to off.
#ssl on OR ssl off
Save and close the file. Then restart the nginx service.
# systemctl restart nginx OR $ sudo systemctl restart nginx
This way, you can enable nginx to handle both HTTP and HTTPS requests for multiple server blocks.
Finally, below is a list of articles about setting up SSL HTTPS on common Linux distributions and FreeBSD.
- Setting Up HTTPS with Let’s Encrypt SSL Certificate For Nginx on RHEL/CentOS
- Secure Nginx with Free Let’s Encrypt SSL Certificate on Ubuntu and Debian
- How to Secure Nginx with SSL and Let’s Encrypt in FreeBSD
That’s all for now. If you know of any other way to solve this error, please let us know via the feedback form below.
Not sure why turning off SSL when SSL is needed as the solution?
Hi,
Doesn’t work for me too and has the same config as zhoulujun
It’s not working, this is my Nginx configuration.