How To Redirect Non WWW to WWW with HTTPS Using Nginx

Sarath Pillai's picture
Redirect to WWW with HTTPS

Nginx is one of the popular web server software used by many companies. One major reason for its popularity is the event-driven model on which the web server is designed. Unlike other popular web servers like Apache, Nginx does not spawn processes to serve each request. Its super fast when it comes to serving static web pages. Apart from these, it can also be used as a caching server & a load balancer. In fact from day one the goal of Nginx web server was mainly "Performance". Basically serve more number of simultaneous requests by using extremely less amount of memory. If you are new to Nginx and is interested to understand why it performs faster compared to Apache, I would recommend reading the below article.

 

Read: How is Nginx Different from Apache?

 

Although a website can be hosted with any name you like(for example abc.example.com, xyz.example.com), people still follow the de facto standard while accessing a website. They generally use www followed by the domain name. Its a convention followed from early days of the internet. Its always a good idea to make your website only accessible via one name.

 

Basically we need a method to redirect a user to www.example.com/blah/blah, even if the user types only example.com/blah/blah on the browser.

 

Apart from this, the number of websites using SSL protocol (HTTPS) is getting increased day by day. Its a good security measure that confirms the identity of the website and brings in encryption to protect data flowing through the wire. The users should be forced to use HTTPS even if they forget to type that in the browser.

 

So anybody who types in http://www.example.com should be redirected to https://www.example.com automatically.

 

How to Redirect Non WWW to WWW in Nginx?

 

Its possible that some of you are only interested in redirecting non www to www to adhere to the general standard. In this section, lets see a configuration snippet in nginx that achieves just that.

 

erver {
    server_name  example.com;
    return       301 http://www.example.com$request_uri;
}
server {
        listen 80 default_server;
        root /usr/share/nginx/html;
        index index.html index.htm;
        server_name www.example.com;
}

The first server block shown above will serve all requests that hits the server with the name of "example.com". It will then return a 301 HTTP status code with the location of "http://www.example.com" followed by rest of the URL that the end user typed.

Once the end user (browser or any http client) gets that 301 response, it will again send the request to the location suggested ( that is http://www.example.com). This request will be served by the second server block which will respond back with the actual data(that is the HTML page). Let's see this practically using curl command(curl is a command line tool to send requests to web servers).

 

curl -vv example.com
* Rebuilt URL to: example.com/
* Hostname was NOT found in DNS cache
*   Trying 10.12.4.215...
* Connected to example.com (10.12.4.215) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: example.com
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
< Server: nginx/1.4.6 (Ubuntu)
< Date: Tue, 04 Jul 2017 15:28:33 GMT
< Content-Type: text/html
< Content-Length: 193
< Connection: keep-alive
< Location: http://www.example.com/

 

 

Note the fact that the lines beginning with > indicates the headers of the HTTP request being sent. Lines beginning with < indicates HTTP response being returned by the server(which clearly shows 301 status, with the value of "http://www.example.com" in the Location field. Browsers and other clients obey this response, and will then send another request to the "Location". This is how 301 redirection works).

 

Important: Please note the fact that DNS entries should be there for example.com and www.example.com (pointing to the same IP) for this to work.

 

How to Redirect HTTP to HTTPS in Nginx?


Now lets see how to solve our second problem. This is to enforce https for all the users visiting your website. Basically any request in the form of http://www.example.com should be redirected to https://www.example.com

Let's see an example nginx configuration snippet which achieves this.

 

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}
server {
        listen 443 default_server ssl;
        server_name example.com www.example.com;
        ssl_certificate    /etc/nginx/server.crt;
        ssl_certificate_key    /etc/nginx/server.key;
        root /usr/share/nginx/html;
        index index.html index.htm;
}

 

The only thing worth noticing is the use of HTTPS in the URL after 301. server_name indicates the website name defined in both the server blocks. Remember to include server_name in your configuration for this to work. If there is no server_name set, then it wont work. This is because server_name variable will be blank without setting it, and it will be a redirection to https:///.

Also remember to have the second server section with appropriate SSL certificate in the correct path.

 

There is another method to do this HTTP to HTTPS redirection in nginx(shown below)

 

server {
    listen 80;
    server_name example.com www.example.com;
    rewrite     ^   https://$server_name$request_uri? permanent;
}
server {
        listen 443 default_server ssl;
        server_name example.com www.example.com;
        ssl_certificate    /etc/nginx/server.crt;
        ssl_certificate_key    /etc/nginx/server.key;
        root /usr/share/nginx/html;
        index index.html index.htm;
}

 

The only difference between the above two methods is the use of rewrite instead of return.  So which one to use? Well the first method of using return is always the best and recommended. This is because return will always perform better than rewrite.

Return does not require the reading of URL string component. It simply returns a 301 irrespective of whatever request hits there. The rewrite module is much better suited for complete URL rewriting. For example, any request that hits http://www.example.com/abc-xyz should now be rewritten to http://www.example.com/abc_xyz.

 

How to redirect non www to www with HTTPS?

This is for those of you who need to redirect any request that hits the server to https://www. For example a request like http://example.com/something should be redirected to https://www.example.com/something. This is the best approach i believe almost all websites should take(as HTTPS is the most recommended, and www and having one name all across for your website is really good from SEO perspective as well.)

 

Let's see an example nginx snippet that will achieve this.

 

server {
    listen 80;
    server_name example.com www.example.com;
    rewrite     ^   https://$server_name$request_uri? permanent;
}
server {
        listen 443 default_server ssl;
        server_name example.com www.example.com;
        if ($host = 'example.com') {
      return 301 https://www.example.com$request_uri;
    }
        ssl_certificate    /etc/nginx/server.crt;
        ssl_certificate_key    /etc/nginx/server.key;
        root /usr/share/nginx/html;
        index index.html index.htm;
}

 

The only thing different here is the if statement inside the second server block. Without that if statement, any user can directly send a request like https://example.com/ and it will work. Basically we needed a logic inside the second server block to add www part.

Rate this article: 
Average: 3.5 (397 votes)

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.