Asked  6 Months ago    Answers:  4   Viewed   27 times

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.com to go to mysite.com 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.com 192.192.6.8 A type at 300 seconds
www.site.com 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.

 Answers

80

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.com;
        # $scheme will get the http protocol
        # and 301 is best practice for tablet, phone, desktop and seo
        return 301 $scheme://domain.com$request_uri;
}

server {
        listen 80;
        server_name domain.com;
        # 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.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}

server {
    server_name  domain.com;
    #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.com to www.domain.com, you can use this:

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    server_name  www.domain.com;
    #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;
       }
}
Tuesday, June 1, 2021
 
Zach
answered 6 Months ago
84

Please note that my SSL certificate is issued for website.com and not www.website.com.

That is your main problem. You are never going to be able to redirect from www to non www without a valid certificate for www. The reason is the connection is handled first before the web server processes anything else including any rewrite rules. So when your browser connects to your site using the https protocol, it has to check for a valid certificate because that's the very nature of SSL to make sure the connection is secure. Then once that is done, Apache will process web server rules that you have in place like rewrites. So it can't rewrite from www to non www until the connection is completed correctly. In order for that to happen you also need a certificate for www as well. The rewrite rules are not the problem.

This topic comes up quite frequently and there is no way around it. That's the nature of SSL/encryption and how it works.

When buying a cert, try not buying just the domain name, because some CA's will only give you that without www. But if you use www.example.com in your CSR you will get both www.example.com and example.com in the same certificate 99% of the time. Then you won't have to worry about this issue. They are stupid cheap so it shouldn't be an issue to get another one. SSls.com has them for 4.99/yr.

Friday, August 27, 2021
 
Nitesh
answered 3 Months ago
19

Well I guess I don't really need the outer "if" statement since I'm only checking for domains of the form xxx.xxx anyways. The following works for me, though it's not robust. Let me know if there is a better solution.

    if ($host ~* ^([a-z0-9-]+.(com|net|org))$) {
        set $host_with_www www.$1;
        rewrite ^(.*)$ http://$host_with_www$1 permanent;
    }

Edit: Added hyphen to the regular expression since it is a valid character in a hostname.

Saturday, September 4, 2021
 
Craig Ringer
answered 3 Months ago
71

You are rewriting www.domain.com on first few lines of nginx.conf. If i'm not wrong, rewriting and redirecting are different things. Try this on first server block;

server {
    server_name  www.mydomain.com;
    return       301 http://mydomain.com$request_uri;
}

and change

server_name mydomain.com www.mydomain.com

to

server_name mydomain.com

in second server block.

Friday, October 8, 2021
 
hakimoun
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share