Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

How do I redirect an request at www. to the non-www version?

This should include requests to the root domain as well as any (wildcard) subdomain.

I also don't want any unnecessary if statements, as per the nginx pitfalls document.

Here's what I have so far but it only seems to work for the root domain, not subdoamins.

server {
  listen 80 default_server;
  server_name www.*;
  rewrite "^www\.(.*)" $scheme://$1 permanent;
}
share|improve this question
1  
You may have some success with server {listen 80 default_server; server_name ~^(www\.)?(?<domain>.+)$; rewrite ^ $scheme://$domain permanent;} - (unfortunately, I can't test it at the moment). It would be simpler if you aren't using a variable domain name - but this should work for any domain name, and an (optional) www subdomain) –  cyberx86 Feb 22 '12 at 0:01
add comment

3 Answers 3

up vote 0 down vote accepted

My understanding of your question is the following: Redirect all requests reaching any subdomain of an arbitrary root domain to the root domain - in a reasonably general manner. For example:

  • www.example1.com -> example1.com
  • abcd.example2.com -> example2.com
  • *.exampleN.com -> exampleN.com

Let's start with the easy case first - a known root domain, with any subdomain:

server{
    server_name *.example.com;
    rewrite ^ $scheme://example.com permanent;
}

server{
    listen 80 default_server;
    server_name example.com;
    #your main config
}

This is fairly well optimized - no if statements, no unnecessary captures in the rewrite - and wildcard server_names are hashed for performance. The first server block matches any subdomain and will issue a redirect to the second server block which only matches the root domain. (Note, although it is easy to match both conditions in one server block (server_name .example.com - no * needed) the two server blocks are needed to prevent a redirect loop).

The more generalized case requires some way of identifying the domain, since it is 'unknown'. We therefore need to parse the server_name - and can do so with a regex capture.

server{
    server_name   ~^(.+\.)(?<domain>.+\..+)$;
    rewrite ^ $scheme://$domain permanent;
}

server{
    listen 80 default_server;
    server_name _;
    #your main config
}

Here we have a (required) subdomain - (.+\.) means any character (.) repeated one or more times (+) followed by an actual '.' (escaped with the backslash) - this capture will be assigned to $1 if we need it.

The next section is very similar - we are using Perl 5.1/PCRE7 notation for a 'named capture' - ?<domain> assigns the capture to $domain. Our domain can be anything (.) one or more characters in length (+), followed by an actual '.' and then another set of any characters (the TLD). This regex will not work for TLDs which contain a '.' - e.g. 'co.uk' - if you will be using those, it is probably best to specify the valid TLDs in your regex. For example:

server_name ^(.+\.)(?<domain>.+\.(co\.uk|net|org|com))$

We use the same rewrite as above, just replacing the static root domain with the captured domain.

Since a common case with the 'unknown' domain scenario will see you passing the same files to all the domains, you probably don't need to capture the domain name in the default_server block (it is more efficient to avoid the regex when possible).

It is important to note that regex matches have the lowest priority - exact names, and wildcard entries take precendence over regexes. Additionally, unlike exact names and wildcard entries - regexes are not hashed. Finally, when using regexes with captures, even if only one server block is defined, the expression must be evaluated for every request to obtain the captures.

As a result of the above, if you do have to do something specific with a particular domain name, simply define a new server block for it and that will take precedence over the default_server block defined above.

If you know the domain names, even if they are numerous, you will get better performance if you can include the static name instead of using a regex. That said, there are some cases (e.g. allowing users to point their (unknown) domain at your IP as part of a service) where you may not know the domain and where the regex approach is necessary.

(Of course, this needs a matching wildcard DNS entry for the requests to ever reach the server.)

share|improve this answer
add comment

There are a couple of ways to do this. Set up a configuration file for www.servername.org domain name, and give it a general redirect to servername.org OR add the following into your config instead of your rewrite line.

if ($host = 'www.site.com' ) {
    rewrite ^/(.*)$ http://site.com/$1 permanent;
}
share|improve this answer
add comment

Keep it simple.

 server {
  listen       80;
  server_name  nginx.org  www.nginx.org www1.nginx.org;
  ...
 }

http://nginx.org/en/docs/http/server_names.html

Better still

 server {
  listen       80;
  server_name  *;
  ...
 }

Or is this too simple?

share|improve this answer
    
no explanation on why the downvote? charming... –  sdolgy Feb 22 '12 at 11:38
1  
I didn't cast the downvote - but the likely reason is because your examples don't do any redirection. The question was not simply to handle responses to both the root domain and the subdomain, but also to redirect all requests to the root domain (likely for SEO purposes - to avoid having multiple sites serving the same content). –  cyberx86 Feb 23 '12 at 0:47
    
helpful feedback. thanks. –  sdolgy Feb 23 '12 at 0:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.