I mentioned in the comments of Chris' answer that you can use wildcards and regex in the server_name and those will get passed to your your rails instance.
server_name *; # handle requests from all domains
There are four ways to use this in your Rails app (that I'm aware of).
The "Big Bag of Content" Method
Do Nothing
If you just let Nginx send all the domains to the same rails app, they all get the same content. In this scenario, www.abc.com and www.xyz.com can access the same data. It's the easiest to do, because you don't do anything.
The limitation of this solution comes when you want to let the domains have different content. For instance, it gets tricky if www.abc.com/about and www.xyz.com/about are supposed to be different pages.
The "Man Behind the Curtain" Method
Using Nginx's "rewrite"
Under certain circumstances, you can let Nginx rewrite the domain name into a subdomain and pass that to your rails app. For example:
server_name *; # handle requests from all domains
rewrite ^(?:www.)?([^.]*)\..*$ $1.yourdomain.com last;
That regex needs a little explanation. It just says get the just the xyz from any of these: www.xyz.com, xyz.com, xzy.co.uk, www.xyz.co.uk. The rewrite changes the request from any of those to xyz.yourdomain.com.
The advantage of this is that Nginx does this very quickly, the rails app isn't involved until later, and requesting content can be restricted to the subdomain. Page.where(subdomain: request.subdomain, permalink: params[:permalink]) for example.
This is pretty restrictive, though, because it means the subdomain and domain name have to be the same. Maybe that's a problem for your application, maybe not. But although I use $1 here in the subdomain, you could just as easily insert it as a parameter in the url. For instance, yourdomain.com/$1 would rewrite the request from www.xyz.com to yourdomain.com/xyz.
Another problem with this is "the man behind the curtain". Although the user visits www.xyz.com the rewrite means they'll see xyz.yourdomain.com in the address bar.
The "Rails Way" Method
Using the Rails request object in the ApplicationController
You can use your application controller to scope the content associated with the domain name using Rails' request object.
In this example, we'll use the ApplicationController to look up the user account associated with the domain name. Assuming you have a User model with a domain_name attribute:
def domain_user
@domain_user ||= User.where(domain_name: request.domain()).take
end
Redis can be used to cache these lookups if the additional hits to your database creates a performance barrier. I haven't reached that point in my apps thus far.
The weakness of this solution is that although the lookup might find www.xyz.com, it would miss xyz.com. To accommodate this, we can use some regex:
def domain_user
request.domain.match /(?:www.)?(.*)/
@domain_user ||= User.where(domain_name: $1).take
end
This regex strips off the www. if it is present. The rest becomes the domain (which ruby stores for us in $1).
Unlike the Nginx rewrite solution, if the user visits www.xyz.com, that's what they still see in the address bar.
Using Routing Constraints
The "Doesn't Work for Me" Method
Alternatively, Rails 3 and above have constraints, functions that exist in your routes file that generate the routing table semi-dynamically. I say "semi-dynamically" because the routing table is generated when the app starts. If the User model (in our example) changes, special attention needs to be given to rebuilding the route table. For apps spread across multiple servers, this can become unwieldy to manage, although people have done it.
Thus far, all of my apps have eventually, if not initially, used the ApplicationController solution because it turned out to be the cleanest and most easily implemented. It also makes a lot of sense from the MCV perspective.