Nginx config for www to non-www and non-www to www redirection


There are many ways to force Nginx to use either WWW version or non-WWW version of URLs for your site.

We use following codes all the time.

Redirect non-www to WWW

Single domain

server {
        server_name example.com;
        return 301 $scheme://www.example.com$request_uri;
}

All domains

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
}

From WWW to non-WWW

Single domain

server {
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
}

All domains

server {
        server_name "~^(?!www\.).*" ;
        return 301 $scheme://www.$host$request_uri;
}

In both cases, for other-www, we create a altogether different server { } block. IMHO, this is cleanest and optimised way to handle www to non-www and non-www to www redirection.

There are some WordPress plugins available there which can handle this at PHP-level. But for performance reason, always handle things in Nginx, that can be handled in Nginx alone! ;-)

30 Comments

  1. Staff

    Instead of hardcodes http we can use $scheme

    OLD:
    return 301 http://example.com$request_uri;

    New:
    return 301 $scheme://example.com$request_uri;

  2. Is it true that www if not redirected permanently to non-www, will hurt site ranking and Google would see it as duplicate contents?

  3. hello thanks for the guide, im using redirect non to www
    the code “for all domain” works for me but the single domain code is not work

  4. Can you tell me what’s the difference here between single and all domain.
    If I need to strip www from even all the subdirectories then what shall be used ?

  5. Actually, I am an apache user and very new to nginx so please tell me where to save these codes under which directory and with what file name and file type?
    As there is nothing like .htaccess for nginx

  6. Staff

    The single domain config will add a redirection only to a specific domain that you have mentioned in the configuration. Hence, the config in the post has example.com domain which you can replace with the specific single domain.

    The All domains config will add it to all the domains for which requests are made on the server.

    These config will be added to your Nginx configuration file. It will typically be under

    /etc/nginx/sites-available/example.com

    Once you add the rule test your nginx configuration by

    nginx -t

    If the test is passed then reload the Nginx process by

    service nginx reload
  7. I don’t know if it’s a typo or something, but for me, to redirect WWW to Non-WWW I had to flip your code this way:

    server {
    server_name “~^www\.(.*)$” ;
    return 301 $scheme://$1$request_uri;
    }

  8. Its not working for me. I tried many options of putting server {
    server_name “~^(?!www\.).*” ;
    return 301 $scheme://www.$host$request_uri;
    }
    but nothing works for me.
    Here is my sites available file http://pastebin.com/aTy9xtca

    • Author

      I think above 2 lines are losing precedence to *.bestdocumentariesonline.com
      Reference: http://nginx.org/en/docs/http/server_names.html

      In that case you can try adding a line like below index line inside server {..} block

      if ( $http_host ~* "www\.(.*)") {
                       rewrite ^ http://$1$request_uri permanent;
      }

      Please be careful about first line as I am writing it without tasting.

      • Thanks Rahul but nothing works for me:(. I added your line and same, also I added this line server {
        server_name “~^(?!www\.).*” ;
        return 301 $scheme://www.$host$request_uri;
        } also in nginx.conf file so also isnt working (basically I try all these lines on different positions and same again. when without www it shows all ok when with www Server not found. Maybe problem in this that my http://www.mysite.com was never reachable? Maybe I should do something to bring this www to live site and then to redirect. ?

      • Thanks Rahul but not success. I added this line and I was trying with different lines different positions and even different files f.e. ngnix.conf (where I should exactly add this line?)
        I think that problem can be because my www never was reachable . Maybe I should do something to make it reachable and to point to my site and then to redirect?

        • Author

          Sorry for delayed reply. At this point, I won’t be able to debug further via comments only.

          You need to make sure:

          1. For all desired domains, DNS lookup reaches to your server’s IP.
          2. Nginx server_name block as wildcard e.g. *.example.com and/or listening by default on that IP. “listening by default” is recommended for domain-mapping.
          3. You need to use rules like I posted in previous comment “if server_name starts with www, regex to fetch domain/hostname without www and redirect to it”

          There are few more ways and tricks but its not possible for me to debug it like this. You can give it a try, or may hire somebody as a last resort.

          • Thanks Rahul. You idea brought me to solve this issue with redirection.
            Only I don’t know if I did it right way (to not have further problems).
            What I did: I added 2 CNAME records in my dns:
            CNAME * @
            CNAME www @
            and also your line for this article and all is redirecting now properly.
            What o you think is this all correct way as I newer heard for www line before.
            Cheers!

          • Author

            You don’t need CNAME record for WWW. It will be covered by wildcard record in your case.

  9. Putting it in to nginx.conf inside http { } but it’s not working.

  10. No error, it just not redirecting from www to non-www. Using nginx as reverse proxy with apache.

  11. I am very impress with your all article.

    Please guide how do we enable functionality for http://www.subdomains.domain.com where subdomains list come from database namse is subdomain.php . i tried following which is not working

    server {
    listen 80;
    server_name www.domain.com *.domain.com;
    ............

    **if ($http_host !~ "^(www\.)?domain\.com"){
    rewrite !^subdomain\.php$ /subdomain.php break;
    }**

    location / {
    root /usr/share/nginx/html/domain.com/;
    index index.php;
    .......

  12. I would like to redirect one page on my site to homepage. Without affecting sub-pages..

    like redirecting site.com/abc to site.com without getting redirect loop in site.com/abc/xyz

    How can that be done? I read about modifying conf file in /etc/nginx… but in my case there is no nginx directory within etc.

  13. Hey Rahul,

    I’ve tried this, and few more things but I can’t make non-www version to work!
    Please take a look, it all seems good:

    [code]
    # I added this later, first I was using your code.. #
    server {
    listen 80;
    server_name mydomain.com;
    return 301 http://www.mydomain.com$request_uri;
    }

    server {
    listen 80; ## listen for ipv4; this line is default and implied
    server_name http://www.mydomain.com;

    access_log /srv/www/mydomain.com/logs/access.log;
    error_log /srv/www/mydomain.com/logs/error.log debug;

    root /srv/www/mydomain.com/public_html;
    index index.php;

    if (!-e $request_filename) {
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;
    rewrite ^/demo(/[^/]+)?(/wp-.*) /demo$2 last;
    rewrite ^/demo(/[^/]+)?(/.*\.php)$ /demo$2 last;
    }

    location / {
    try_files $uri $uri/ /index.php?$args ;
    }

    location /demo {
    try_files $uri $uri/ /demo/index.php?$args ;
    }

    rewrite ^/download/([^/]+)$ http://www.mydomain.com/wp-content/plugins/download-monitor/download.php$

    location ~ \.php$ {
    try_files $uri /demo/index.php;
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    }

    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|r$
    access_log off; log_not_found off; expires max;
    }

    location = /robots.txt { access_log off; log_not_found off; }
    location ~ /\. { deny all; access_log off; log_not_found off; }
    }
    [/code]

    www version is working, but non www is not redirected, no matter what I put in config file.
    I have one more domain on my VPS, and I’m not sure if that’s causing the issue (shouldn’t be, but while I was experimented I was redirected to first domain, this is second).

    Any idea?

  14. While trying to see in Chrome I can see “resolving host” in bottom left corner, and then “Oops! Google Chrome could not find domain”. Domain has been moved from shared hosting, where there were www version has been redirected.

    I tried deactivating plugins, it’s not helping, tried to change in db everything to www, but everything is with http://www...
    Now I’m not sure should I use different port for each website, both are on 80?

    Thank you, and sorry for the long question…. :(


Comments are closed on this article.
Please use free our support forum for support and discussions.

People Who Like Thisx

Loading...