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.

I am hosting a Rails app on Nginx that is accessible through a defined set of domains. For each of these domains I also want to forward www to non-www. Right now my config file looks like this:

server {
    listen      80;
    server_name www.domain1.com;
    rewrite ^ http://domain1.com$uri permanent;
}

server {
    listen      80;
    server_name www.domain2.com;
    rewrite ^ http://domain2.com$uri permanent;
}

server {
    listen      80;
    server_name www.domain3.com;
    rewrite ^ http://domain3.com$uri permanent;
}

server {
    listen            80;
    server_name       domain1.com domain2.com domain3.com;
    root              /home/rails/apps/myapp/current/public;
    passenger_enabled on;
}

So I have to repeat the part that forwards www to non-www for every domain and add that domain as a server_name to the last server {} directive. Right now I have about 15 domains configured like that and there are more to come, meaning it will get more and more cumbersome to maintain that list. What I would really like would be something like this: (pseudocode)

%domains = [domain1.com, domain2.com, domain3.com]

for each %domain in domains
    server {
        listen      80;
        server_name www.%domain;
        rewrite ^ http://%domain$uri permanent;
    }
end

server {
    listen            80;
    server_name       %domains;
    root              /home/rails/apps/myapp/current/public;
    passenger_enabled on;
}

One thing I cannot do is use a wildcard for forwarding ALL domains to their non-www variant, since I host other domains on the same Nginx as well. It has to be a defined set of domains.

Is there any way to accomplish anything like that? Or another way I could clean up the config file? All suggestions welcome!

EDIT:

With the help of rzab's answer I could get it down to this:

map $http_host $non_www_host {
  www.domain1.com domain1.com;
  www.domain2.com domain2.com;
  www.domain3.com domain3.com;
}

server {
  listen        80;
  server_name   www.domain1.com www.domain2.com www.domain3.com;
  rewrite ^     http://$non_www_host$uri permanent;
}

server {
    listen              80;
    server_name         domain1.com domain2.com domain3.com;
    root                /home/rails/apps/myapp/current/public;
    passenger_enabled   on;
}

It's less to write (maybe not with 3 domains but with more than 5 or more definitely) but now I have to add a new domain to 3 places! Is there any way I can just have the list of domains in one place?

share|improve this question
    
Write a script to generate a config file, that's about the only thing you can do aside from a wildcard server block. –  Martin Fjordvald Mar 29 '11 at 12:15
    
Nginx favors static server names before regexps –  Alexander Azarov Mar 29 '11 at 13:16

2 Answers 2

You can auto-generate 2 small files containing a map of hosts and server_name line, so that the full config would include

map $http_host $nonwww_host {
        www.domain1.com domain1.com;
        www.domain2.com domain2.com;
        # etc.
}

server {     
        server_name www.domain1.com www.domain2.com; # etc.
        rewrite ^ http://$nonwww_host$uri permanent;
}

Having 2 files (lets say, hostmap.conf and server_names.conf), the config can have

include hostmap.conf; # instead of "map $http_host $nonwww_host { ..."

server {
        include server_names.conf; # "server_name ..."
        rewrite ^ http://$nonwww_host$uri permanent;
}    
share|improve this answer
    
Thanks for your tip with using a map! I updated the post. I wouldn't extract the domains into external files, though. Then I would have to remember to update several files anytime I want to add a domain. However, with the map I now have 3 places I have to add a new domain. Is there any way of defining the domains in just one place? –  Manuel Meurer Apr 3 '11 at 16:56
server {
        server_name ~^www\.(domain1\.com|domain2\.com|domain3\.com)$;
        set $non_www_host $1;
        rewrite ^ http://$non_www_host$uri permanent;
}

You need at least 0.7.40 nginx for regex in server_name support.

2) multiple regexes to split a long one with more than a few names.

server_name ~^www\.(domain1\.com|domain2\.com|domain3\.com)$;
server_name ~^www\.(domain4\.com|domain5\.com|domain6\.com)$;

3) multiple server_names. Looks obvious but I thought you want it to be concise

server_name www.domain1.com;
server_name www.domain2.com;
# etc.
share|improve this answer
    
This would be another option but the regex would get very long and cumbersome to work with as well once you have 10+ domains... besides, would it have an impact on performance using a regex instead of a static string? –  Manuel Meurer Apr 5 '11 at 7:16
    
Pick you preference :) Regex to be concise. Multiple "server_name"s to be readable. You can have multiple server_names with regexes too, so they won't get that long. I'm updating the answer with the examples. –  rzab Apr 5 '11 at 9:52
    
Performance-wise, regexes are ok as long as you're not eager for a benchmark to see if it's ok. Static string is the fastest, but I cannot tell if regex performance is acceptable in your situation. –  rzab Apr 5 '11 at 10:03

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.