39

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.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
on3al
  • 2,090
  • 4
  • 20
  • 19

8 Answers8

18

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;
}
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Mohammad AbuShady
  • 40,884
  • 11
  • 78
  • 89
  • 1
    This is exactly what I wanted and am using it the other way around. Thank you! – Danijel-James W Jan 30 '14 at 02:31
  • You'll need a separate server with server name `www.domain.com` and liatens to port 80 to do that aditional redirect if you need it. – Mohammad AbuShady Aug 19 '14 at 14:32
  • 3
    This gives me - `nginx: [emerg] invalid parameter "443" in /etc/nginx/nginx.conf:96` – sarat Oct 18 '14 at 11:27
  • could u paste that line '96', also your nginx version – Mohammad AbuShady Oct 18 '14 at 11:44
  • This is also giving me `nginx: [emerg] invalid parameter "443"` - Something must have changed. Using nginx 1.6.2 – Berto Oct 21 '14 at 18:27
  • 4
    I just tested it on that version, it gave me the same too, you can split it into two listen lines `listen 80;` and `listen 443;` – Mohammad AbuShady Oct 21 '14 at 21:35
  • could someone explain why you need a working certificate for the none-www domain, since, this is a plaine redirection that leads to a new request with the www.domain ? – haemse Oct 31 '17 at 22:22
  • @haemse because what the browser does ( roughly ) is it creates a connection to the non www domain ( the url you requested ), gets the certificate and validates it, then if things are ok it would ask for the response ( the redirect ), so you get the certificate failure before getting the redirect response. – Mohammad AbuShady Nov 01 '17 at 10:08
  • @MohammadAbuShady: Ok, so in short, without the cert, it does not even build up a connection ... – haemse Nov 01 '17 at 15:44
  • @haemse yea, you'll get the invalid certificate error from the browser – Mohammad AbuShady Nov 01 '17 at 19:38
13

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.

Suneel Kumar
  • 5,621
  • 3
  • 31
  • 44
1

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;
    }
}
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Sushil
  • 2,324
  • 1
  • 27
  • 26
0
#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;
        }
}
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Ranch Camal
  • 501
  • 1
  • 4
  • 12
0

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.

rjhcnf
  • 762
  • 6
  • 12
0

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

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Yagnesh bhalala
  • 1,107
  • 1
  • 15
  • 17
0

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.

Artyom Vancyan
  • 5,029
  • 3
  • 12
  • 34
0

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

Luke Schoen
  • 4,129
  • 2
  • 27
  • 25