NGINX: HTTP to HTTPS redirect not working
Solution 1
Please use $server
instead of $host
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Please refer below docs. might be helpful https://www.digitalocean.com/community/questions/best-way-to-configure-nginx-ssl-force-http-to-redirect-to-https-force-www-to-non-www-on-serverpilot-free-plan-by-using-nginx-configuration-file-only
Solution 2
I'm answering this although it's been accepted because I think the answer is wrong.
I'm pasting your config below as-is, with only a comment pointing to the wrongly placed (extra it seems) curly bracked closing the server block:
server {
listen 443 ssl default_server;
server_name example.com
server_tokens off;
charset utf-8;
} <--------- CLOSED BLOCK WITH EXTRA BRACKET
... SSL config stuff ...
location / {
proxy_pass http://localhost:8000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
}
}
server {
listen 80;
server_name example.com
return 301 https://$host$request_uri;
}
The recommended way is to use the $host
as you had it initially. The $server_name
variable will be replaced by the virtualhost definition instead of the URL entered by the user. This could cause you problems if you are using server_alias for example. You can read the definition of each variable in the official nginx documentation. Here is a quote:
$server_name
name of the server which accepted a request
$host
in this order of precedence: host name from the request line, or host name from the “Host” request header field, or the server name matching a request
So. I think your problem was the curly bracket, and not the variable. You should probably return to the $host and try again if it works.
ps. also remove the proxy_http_version
line and the proxy_set_header
with the empty "", they are not needed unless you have a very specific use-case.
Related videos on Youtube
Kristoh
Updated on September 18, 2022Comments
-
Kristoh over 1 year
First time posting here. I've been searching on here for about two days to find a solution to my problem and nothing is working.
I know, there is a ton of posts about this same problem but none of the threads solutions I have came across, have worked so far. I am using NodeJS w/ Angular 5 on an Amazon EC2 instance.
Navigating to https://example.com works fine. The web page loads correctly. But, http://example.com gives me the "Welcome to nginx!" page.
Here is my nginx server config blocks:
server { listen 443 ssl default_server; server_name example.com server_tokens off; charset utf-8; } ... SSL config stuff ... location / { proxy_pass http://localhost:8000/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Proxy ""; } } server { listen 80; server_name example.com return 301 https://$host$request_uri; }
- Tried changing default_server to the port 80 block
- Tried using $server_name instead of $host on the redirect line
- Tried having the port 80 block on top of the port 443 block
- Checked for syntax errors in the config files (everything is fine)
Also checked for any conflicting files (none that I saw linked to nginx.conf).
curl -I http://example.com HTTP/1.1 200 OK Server: nginx/1.10.3 (Ubuntu) Date: Wed, 18 Jul 2018 04:18:49 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 31 Jan 2017 15:01:11 GMT Connection: keep-alive ETag: "5890a6b7-264" Accept-Ranges: bytes
As you can see, when I curl http://example.com (not actually example.com), it returns a status of 200 rather than 301. Also, the "Network" tab in Firefox's developer tools, shows a status of 304.
-
Kristoh almost 6 yearsI am not sure how or why, but I must be going crazy. I had $server_name instead of $host before I posted my config here but it wasn't working that way either. Now it somehow is. Regardless, thank you so much!
-
Tero Kilkanen almost 6 yearsThere are use cases for both using
$host
and$server_name
. If one has multiple virtual hosts, then$host
can be used to implement the redirect for all virtual hosts. If there is only one virtual host and one wants to implement the redirect for only that host, then$server_name
is better. -
Leo almost 6 yearsNot necessarily only with virtual hosts, $server_name could mess with redirects too, by overwriting the URL to the virtual host definition. Using instead $host variable, you are respecting the user/browser input, as the “Host” header field of the request is tested against the server_name entries of the server blocks.
-
Kristoh almost 6 yearsThat extra bracket was an accident when I was pasting the config over. I tried $host and $server_name before I posted here (as I saw many different reasons from different threads on to use one or the other), i tried IPv6 port configs on both 80 and 443 before I posted as well. All i did was change $host back to $server_name and added the IPv6 port config only for port 80 this time and it worked. Not really understanding why it started working either.