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.)
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