Nginx no-www to www and www to no-www - redirect

I am using nginx on Rackspace cloud following a tutorial and having searched the net and so far can't get this sorted.
I want www.mysite.example to go to mysite.example as normal in .htaccess for SEO and other reasons.
My /etc/nginx/sites-available/www.example.com.vhost config:
server {
listen 80;
server_name www.example.com example.com;
root /var/www/www.example.com/web;
if ($http_host != "www.example.com") {
rewrite ^ http://example.com$request_uri permanent;
}
I have also tried
server {
listen 80;
server_name example.com;
root /var/www/www.example.com/web;
if ($http_host != "www.example.com") {
rewrite ^ http://example.com$request_uri permanent;
}
I also tried. Both the second attempts give redirect loop errors.
if ($host = 'www.example.com' ) {
rewrite ^ http://example.com$uri permanent;
}
My DNS is setup as standard:
site.example 192.192.6.8 A type at 300 seconds
www.site.example 192.192.6.8 A type at 300 seconds
(example IPs and folders have been used for examples and to help people in future). I use Ubuntu 11.

HTTP Solution
From the documentation, "the right way is to define a separate server for example.org":
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
...
}
HTTPS Solution
For those who want a solution including https://...
server {
listen 80;
server_name www.domain.example;
# $scheme will get the http protocol
# and 301 is best practice for tablet, phone, desktop and seo
return 301 $scheme://domain.example$request_uri;
}
server {
listen 80;
server_name domain.example;
# here goes the rest of your config file
# example
location / {
rewrite ^/cp/login?$ /cp/login.php last;
# etc etc...
}
}
Note: I have not originally included https:// in my solution since we use loadbalancers and our https:// server is a high-traffic SSL payment server: we do not mix https:// and http://.
To check the Nginx version, use nginx -v.
Strip www from URL with Nginx redirect
server {
server_name www.domain.example;
rewrite ^(.*) http://domain.example$1 permanent;
}
server {
server_name domain.example;
#The rest of your configuration goes here#
}
So you need to have TWO server codes.
Add the www to the URL with Nginx redirect
If what you need is the opposite, to redirect from domain.example to www.domain.example, you can use this:
server {
server_name domain.example;
rewrite ^(.*) http://www.domain.example$1 permanent;
}
server {
server_name www.domain.example;
#The rest of your configuration goes here#
}
As you can imagine, this is just the opposite and works the same way the first example. This way, you don't get SEO marks down, as it is complete perm redirect and move. The no WWW is forced and the directory shown!
Some of my code shown below for a better view:
server {
server_name www.google.com;
rewrite ^(.*) http://google.com$1 permanent;
}
server {
listen 80;
server_name google.com;
index index.php index.html;
####
# now pull the site from one directory #
root /var/www/www.google.com/web;
# done #
location = /favicon.ico {
log_not_found off;
access_log off;
}
}

Actually you don't even need a rewrite.
server {
#listen 80 is default
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
#listen 80 is default
server_name example.com;
## here goes the rest of your conf...
}
As my answer is getting more and more up votes but the above as well. You should never use a rewrite in this context. Why? Because nginx has to process and start a search. If you use return (which should be available in any nginx version) it directly stops execution. This is preferred in any context.
Redirect both, non-SSL and SSL to their non-www counterpart:
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate path/to/cert;
ssl_certificate_key path/to/key;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
listen 443 ssl;
server_name example.com;
ssl_certificate path/to/cert;
ssl_certificate_key path/to/key;
# rest goes here...
}
The $scheme variable will only contain http if your server is only listening on port 80 (default) and the listen option does not contain the ssl keyword. Not using the variable will not gain you any performance.
Note that you need even more server blocks if you use HSTS, because the HSTS headers should not be sent over non-encrypted connections. Hence, you need unencrypted server blocks with redirects and encrypted server blocks with redirects and HSTS headers.
Redirect everything to SSL (personal config on UNIX with IPv4, IPv6, SPDY, ...):
#
# Redirect all www to non-www
#
server {
server_name www.example.com;
ssl_certificate ssl/example.com/crt;
ssl_certificate_key ssl/example.com/key;
listen *:80;
listen *:443 ssl spdy;
listen [::]:80 ipv6only=on;
listen [::]:443 ssl spdy ipv6only=on;
return 301 https://example.com$request_uri;
}
#
# Redirect all non-encrypted to encrypted
#
server {
server_name example.com;
listen *:80;
listen [::]:80;
return 301 https://example.com$request_uri;
}
#
# There we go!
#
server {
server_name example.com;
ssl_certificate ssl/example.com/crt;
ssl_certificate_key ssl/example.com/key;
listen *:443 ssl spdy;
listen [::]:443 ssl spdy;
# rest goes here...
}
I guess you can imagine other compounds with this pattern now by yourself.
More of my configs? Go here and here.

Best Practice: separate server w/ hardcoded server_name
Best practice with nginx is to use a separate server for a redirect like this (not shared with the server of your main configuration), to hardcode everything, and not use regular expressions at all.
It may also be necessary to hardcode the domains if you're using HTTPS, because you have to know upfront which certificates you'll be providing.
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
server_name www.example.org;
return 301 $scheme://example.org$request_uri;
}
server {
server_name example.com example.org;
# real configuration goes here
}
Using Regular Expressions within server_name
If you have a number of sites, and don't care for the most ultimate performance, but want every single one of them to have the same policy in regards to the www. prefix, then you can use regular expressions. The best practice of using a separate server would still stand.
Note that this solution gets tricky if you use https, as you must then have a single certificate to cover all of your domain names if you want this to work properly.
non-www to www w/ regex in a dedicated single server for all sites:
server {
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
www to non-www w/ regex in a dedicated single server for all sites:
server {
server_name ~^www\.(?<domain>.+)$;
return 301 $scheme://$domain$request_uri;
}
www to non-www w/ regex in a dedicated server for some sites only:
It may be necessary to restrict the regex to cover only a couple of domains, then you can use something like this to only match www.example.org, www.example.com and www.subdomain.example.net:
server {
server_name ~^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$;
return 301 $scheme://$domain$request_uri;
}
Testing Regular Expressions w/ nginx
You can test that the regex works as expected with pcretest on your system, which is the exact same pcre library that your nginx will be using for regular expressions:
% pcretest
PCRE version 8.35 2014-04-04
re> #^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$#
data> test
No match
data> www.example.org
0: www.example.org
1: example.org
data> www.test.example.org
No match
data> www.example.com
0: www.example.com
1: example.com
data> www.subdomain.example.net
0: www.subdomain.example.net
1: subdomain.example.net
data> subdomain.example.net
No match
data> www.subdomain.example.net.
No match
data>
Note that you don't have to worry about trailing dots or case, as nginx already takes care of it, as per nginx server name regex when "Host" header has a trailing dot.
Sprinkle if within existing server / HTTPS:
This final solution is generally not considered to be the best practice, however, it still works and does the job.
In fact, if you're using HTTPS, then this final solution may end up easier to maintain, as you wouldn't have to copy-paste a whole bunch of ssl directives between the different server definitions, and could instead place the snippets only into the needed servers, making it easier to debug and maintain your sites.
non-www to www:
if ($host ~ ^(?!www\.)(?<domain>.+)$) {
return 301 $scheme://www.$domain$request_uri;
}
www to non-www:
if ($host ~ ^www\.(?<domain>.+)$) {
return 301 $scheme://$domain$request_uri;
}
hardcoding a single preferred domain
If you want a little bit more performance, as well as consistency between multiple domains a single server may use, it might still make sense to explicitly hardcode a single preferred domain:
if ($host != "example.com") {
return 301 $scheme://example.com$request_uri;
}
References:
http://nginx.org/r/server_name
http://nginx.org/r/return
http://nginx.org/en/docs/http/server_names.html

You may find out you want to use the same config for more domains.
Following snippet removes www before any domain:
if ($host ~* ^www\.(.*)$) {
rewrite / $scheme://$1 permanent;
}

You need two server blocks.
Put these into your config file eg /etc/nginx/sites-available/sitename
Let's say you decide to have http://example.com as the main address to use.
Your config file should look like this:
server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name example.com;
# this is the main server block
# insert ALL other config or settings in this server block
}
The first server block will hold the instructions to redirect any requests with the 'www' prefix. It listens to requests for the URL with 'www' prefix and redirects.
It does nothing else.
The second server block will hold your main address — the URL you want to use. All other settings go here like root, index, location, etc. Check the default file for these other settings you can include in the server block.
The server needs two DNS A records.
Name: # IPAddress: your-ip-address (for the example.com URL)
Name: www IPAddress: your-ip-address (for the www.example.com URL)
For ipv6 create the pair of AAAA records using your-ipv6-address.

Here's how to do it for multiple www to no-www server names (I used this for subdomains):
server {
server_name
"~^www\.(sub1.example.com)$"
"~^www\.(sub2.example.com)$"
"~^www\.(sub3.example.com)$";
return 301 $scheme://$1$request_uri ;
}

I combined the best of all the simple answers, without hard-coded domains.
301 permanent redirect from non-www to www (HTTP or HTTPS):
server {
if ($host !~ ^www\.) {
rewrite ^ $scheme://www.$host$request_uri permanent;
}
# Regular location configs...
}
If you prefer non-HTTPS, non-www to HTTPS, www redirect at the same time:
server {
listen 80;
if ($host !~ ^www\.) {
rewrite ^ https://www.$host$request_uri permanent;
}
rewrite ^ https://$host$request_uri permanent;
}

This solution comes from my personal experience. We used several Amazon S3 buckets and one server for redirecting non-www to www domain names to match S3 "Host" header policy.
I used the following configuration for nginx server:
server {
listen 80;
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
This matches all domain names pointed to the server starting with whatever but www. and redirects to www.<domain>. In the same manner you can do opposite redirect from www to non-www.

try this
if ($host !~* ^www\.){
rewrite ^(.*)$ https://www.yoursite.example$1;
}
Other way:
Nginx no-www to www
server {
listen 80;
server_name yoursite.example;
root /path/;
index index.php;
return 301 https://www.yoursite.example$request_uri;
}
and www to no-www
server {
listen 80;
server_name www.yoursite.example;
root /path/;
index index.php;
return 301 https://yoursite.example$request_uri;
}

Redirect non-www to www
For Single Domain :
server {
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
For All Domains :
server {
server_name "~^(?!www\.).*" ;
return 301 $scheme://www.$host$request_uri;
}
Redirect www to non-www
For Single Domain:
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
For All Domains :
server {
server_name "~^www\.(.*)$" ;
return 301 $scheme://$1$request_uri ;
}

Unique format:
server {
listen 80;
server_name "~^www\.(.*)$" ;
return 301 https://$1$request_uri ;
}

If you don't want to hardcode the domain name, you can use this redirect block. The domain without the leading www is saved as variable $domain which can be reused in the redirect statement.
server {
...
# Redirect www to non-www
if ( $host ~ ^www\.(?<domain>.+) ) {
rewrite ^/(.*)$ $scheme://$domain/$1;
}
}
REF: Redirecting a subdomain with a regular expression in nginx

location / {
if ($http_host !~ "^www.domain.example"){
rewrite ^(.*)$ $scheme://www.domain.example$1 redirect;
}
}

not sure if anyone notice it may be correct to return a 301 but browsers choke on it to doing
rewrite ^(.*)$ https://yoursite.example$1;
is faster than:
return 301 $scheme://yoursite.example$request_uri;

Ghost blog
in order to make nginx recommended method with return 301 $scheme://example.com$request_uri; work with Ghost you will need to add in your main server block:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_pass_header X-CSRF-TOKEN;
proxy_buffering off;
proxy_redirect off;

my configuration was - Nginx + tomcat 9 + Ubuntu 20.04 + spring boot app
all answers above not working for me - also not work upstream notation in Nginx file - so I change my settings on this
thanks God for certbot - this util very helpful, it's generate base file for your site and then I added my changes - to redirect https://www.example.com, http://www.example.com to only one https://example.com
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
}
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080; # This is upstream name, note the variable $scheme in it
proxy_redirect off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}

if ($host ~* ^www.example.com$) {
return 301 $scheme://example.com$request_uri;
}

Add CNAME with cloudflare and use this format as conf file.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass "http://localhost:3000/";
}}

If you are having trouble getting this working, you may need to add the IP address of your server. For example:
server {
listen XXX.XXX.XXX.XXX:80;
listen XXX.XXX.XXX.XXX:443 ssl;
ssl_certificate /var/www/example.com/web/ssl/example.com.crt;
ssl_certificate_key /var/www/example.com/web/ssl/example.com.key;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
where XXX.XXX.XXX.XXX is the IP address (obviously).
Note: ssl crt and key location must be defined to properly redirect https requests
Don't forget to restart nginx after making the changes:
service nginx restart

Related

Nginx 301 Redirect http (naked and www) to https www, plus wildcard subdomain to https

I'm trying to set up an Nginx proxy server for a multi-tenant Saas with lots of custom domain names. What I want to do is create a server block that can handle the following requests, all as 301 permanent:
http://custom-domain.com to https://www.custom-domain.com (custom-domain.com could be any user-set domain name)
http://www.custom-domain.com to https://www.custom-domain.com (again, any domain name)
http://.saas-domain.com to https://.saas-domain.com (saas-domain,com is a single domain name for my service)
I am currently handling this with a few If statements, but it looks hacky and I am hoping for some help with a more efficient way:
server {
listen 80 default_server;
location / {
# if 'www' redirect to https
if ($host ~* ^(www)) {
return 301 https://$host$request_uri;
}
# if '*.saas-domain.com' redirect to https://*.saas-domain.com
if ($host ~* ^(.*)\.saas-domain\.com) {
return 301 https://$host$request_uri;
}
# if not 'www' redirect to https and add 'www'
if ($host !~* ^(www)) {
return 301 https://www.$host$1 permanent;
}
}
}
Is this the best way to handle all of my scenarios? I think the complication is the wildcard custom domains. I'm concerned with the If statement's overhead. TIA!
Nginx recommend not to use "If" statements unless you have no other way to solve your issue. I would suggest to add separate blocks for your domain names as this will give you more flexibility.
Try the following to see if it helps.
# Capture requests that already have www and redirect to https
server {
listen 80;
server_name www.*;
return 301 https://$server_name$request_uri;
}
# Captures the saas-domain.com requests and redirects them
server {
listen 80 ;
server_name *.saas-domain.com;
return 301 https://$server_name$request_uri;
}
# Default capture everything else and redirect to https://www.
server {
listen 80 default_server;
server_name _;
return 301 https://www.$host$request_uri;
}
Test this first before implementing it in production.
Nginx Server names
Nginx if is evil
Nginx variables

Nginx best way for Multiple server_names redirect non www. to www

My config :
server {
listen 80;
listen [::]:80;
server_name domain.com www.domain.com;
##locations and fastcgi proxy stuff etc down here
}
The way I see everyone else doing a 301 redirect (return) is they create a new server block and put the domain host in there like this
server {
listen 80;
listen [::]:80;
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
##This server block contains no locations etc
}
How can I do a redirect from non-www. to www. without creating a new server block ?
try with:
if ($host ~* "^(?!www)(.*)$") {
set $catch_host $1;
rewrite (.*) http://www.${catch_host}$1 permanent;
}

SSL for domain, including subdomains

I have a domain, example.com. From that, I have these:
blog.example.com
api.example.com
books.example.com
I have acquired SSL cert for root domain and its subdomains.
And I want the redirections to be like so:
http://example.com => https://example.com
http://blog.example.com => https://blog.example.com
http://books.example.com => https://books.example.com
This is my example.com nginx conf
server {
listen 443 ssl default_server;
root /home/django/khophi;
index index.html index.htm;
server_name example.com;
include /etc/nginx/globalssl.conf; //ssl config
}
server {
listen 80 default_server;
server_name example.com;
return 301 https://$host$request_uri;
}
nginx conf for blog.example.com
server {
listen 443 ssl; // now listens for https
root /var/www/html/blog;
index index.php index.html index.htm;
server_name blog.example.com;
#include /etc/nginx/globalssl.conf;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
// error pages
location ~ \.php$ {
//php specific things
}
}
server {
listen 80;
server_name blog.example.com;
return 301 https://blog.example.com$request_uri;
}
books.example.com follows similar structure as blog.example.com conf
What happens With the above setup?
Visit to http://example.com redirects to https://example.com (just as I want
Visit to http://blog.example.com redirects to https://blog.example.com BUT, shows page of https://example.com
In my case, I want:
example.com to remain as default_server
http://example.com to redirect to https://example.com
ALL http:// requested subdomains to redirect to their respective https:// versions
if a subdomain is requested which doesn't exist, it should redirect to default_server (https://example.com)
Instead of using return, i use rewrite instead on the redirection server block on the main domain and its subdomains, like so:
// blog.example.com
server {
listen 80;
server_name blog.example.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
// example.com
server {
listen 80 default_server;
server_name example.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
This link helped

nginx HTTPS Redirect

I'm trying to get my site to use HTTPS only. I've looked all over stackoverflow and tried many of the suggested settings for the nginx settings file for the site, but I still can't get all address combinations to work. What do I need to change in the file to get it to work?
These two address combinations don't redirect -
http://www.example.com > No Redirect (Errors Out)
https://example.com > No Redirect (Errors Out)
Here's what the settings file looks like -
server {
listen [::]:80;
server_name www.example.com;
return 301 https://$host$request_uri;
}
server {
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen [::]:443 default_server ipv6only=off;
server_name example.com www.example.com;
# rest of config file...
}
I accomplish this on my server in the following way:
server {
listen 80;
server_name example.com;
rewrite ^/(.*) https://example.com/$1 permanent;
}
At a glance your configuration looks OK, but the return directive documentation does note some limitations for older versions of nginx that would be encountered with your configuration.
Finally, in the secure server configuration, you could include an HTTP Strict Transport Security directive to cause clients to only connect to your domain over TLS in the future.
add_header Strict-Transport-Security max-age=31536000;
Below config will redirect example.com to https://example.com
server {
listen 80;
server_name *.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name *.example.com;
[....]
}
However, if you want to redirect all domains to https:
change server_name to _ (server_name _;)
replace $server_name variable to $host in redirect rule (return 301 https://$host$request_uri;)
You can use like this
server {
listen 192.168.1.1:443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 192.168.1.2:443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
http://nginx.org/en/docs/http/configuring_https_servers.html

Nginx Redirect HTTP to HTTPS and non-www to ww

I'm setting up an Nginx server with an SSL.
The domain with the SSL is www.mydomain.example
I want to redirect all requests from:
http://mydomain.example, http://www.mydomain.example, & https://mydomain.example to
https://www.mydomain.example
I have the following server blocks setup currently:
server{
listen 443 ssl;
root /www/mydomain.example/;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen 80;
server_name www.mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen ssl 443;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
This currently does not work, but I don't understand why not. I can get a combination of either HTTP -> HTTPS working or no-www to -> www working, but mixing them as above does not work.
The SSL redirect won't work if your SSL certificate doesn't support the non-www domain.
The config is correct but can be reduced to just 1 redirect server
Also don't forget to reload Nginx sudo service nginx reload
server {
listen 80;
listen 443 ssl;
server_name example.com;
# add ssl settings
return 301 https://www.example.com$request_uri;
}
I am late, But you can do like this
server{
listen 443 ssl;
server_name www.mydomain.example;
root /www/mydomain.example/;
ssl on;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name www.mydomain.example mydomain.example;
return 301 https://$server_name$request_uri;
}
server{
listen 443;
server_name mydomain.example;
return 301 https://www.$server_name$request_uri;
}
Or you can replace return 301 https://www.$server_name$request_uri; with rewrite ^ http://www.$server_name$request_uri? permanent;, both will work.
You also need to set this in google webmaster for better SEO.
this works for me for HTTP to HTTPS redirection,
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com;
#For HTTP to HTTPS:
proxy_set_header X-Forwarded-Proto $scheme;
if ( $http_x_forwarded_proto != 'https' )
{
return 301 https://$host$request_uri;
}
location / {
try_files $uri $uri/ /index.php;
add_header 'Access-Control-Allow-Origin' '*';
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Use a rewrite to send all HTTP traffic to HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
This configuration listens on port 80 as the default server for both IPv4 and IPv6 and
for any hostname. The return statement returns a 301 permanent redirect to the
HTTPS server at the same host and request URI.
#If you like to redirect all "http" to "https" then add the following:
server {
listen 80;
server_name yourdomain.example;
server_name www.yourdomain.example;
if ($scheme = "http")
{
rewrite ^(.*)$ https://yourdomain.example$1 permanent;
}
}
Please add two given things on your file.
Code to paste on top:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Code to paste on bottom:
server {
listen 443 ssl http2;
server_name www.example.com;
# . . . other code
return 301 https://example.com$request_uri;
}
Source
I was trying to fix the problem by redirecting the request URI to HTTPS if it was requested with the HTTP scheme. But this solution does not work in some conditions.
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
When we type a domain name in the search bar of a browser, it makes a request with the HTTP scheme by default. This behavior of the browser is not handled by nginx, but it can be done manually. We have to handle 497 status code by adding error_page 497 https://$server_name$request_uri;.
error_page 497 https://$server_name$request_uri;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
What does the 497 indicate, and when occur?
The 497 HTTP Request Sent to HTTPS Port is used when a client has made an HTTP request to a port that is listening for HTTPS requests specifically.
I couldn't figure out why HTTP http://example.com wouldn't redirect to HTTPS https://example.com. i had configured it the following way like others have and according to https://nginx.org/en/docs/http/configuring_https_servers.html, even after restarting the server with nginx -s reload && sudo systemctl restart nginx
/etc/nginx/sites-available/example.com
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 1m;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.example.com example.com;
root /var/www/build;
index index.html;
location / {
try_files $uri /index.html =404;
}
}
But even though i'm using the latest browsers, the redirection from HTTP to HTTPS only works with the latest in incognito window:
Firefox: 110.0 (64-bit) (both on Desktop and Mobile)
But not with the latest in incognito window even after clear cache and hard reload:
Brave: Version 1.48.164 Chromium: 110.0.5481.100 (Official Build) (x86_64)
Chrome: Version 110.0.5481.100 (Official Build) (x86_64)
With Brave and Chrome it just loads the default HTTP page "Welcome to nginx!" from /var/www/html/
index.nginx-debian.html