Search code examples
http-redirectubuntunginxrackspaceno-www

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


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.


Solution

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