on3al
on3al

Reputation: 2130

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.

Upvotes: 39

Views: 36118

Answers (8)

Luke Schoen
Luke Schoen

Reputation: 4503

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

Upvotes: 0

Artyom Vancyan
Artyom Vancyan

Reputation: 5370

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 , 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.

Upvotes: 0

Suneel Kumar
Suneel Kumar

Reputation: 5831

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.

Upvotes: 13

Sushil
Sushil

Reputation: 2490

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;
    }
}

Upvotes: 1

Yagnesh bhalala
Yagnesh bhalala

Reputation: 1315

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

Upvotes: 0

Ranch Camal
Ranch Camal

Reputation: 570

#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;
        }
}

Upvotes: 0

Mohammad AbuShady
Mohammad AbuShady

Reputation: 42789

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;
}

Upvotes: 18

rjhcnf
rjhcnf

Reputation: 1057

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.

Upvotes: 0

Related Questions