How do I serve multiple rails apps on one domain (and sub)? - ruby-on-rails

This is kind of weird but I'd like to serve multiple websites on the same domain. If possible, we want to avoid subdomains to keep urls simple for our users - no need for them to know it's two separate apps. This is purely for keeping the code bases separate. Any ideas?
For example:
Rails App 1 (Refinery CMS) serves:
http://example.com/
http://example.com/about
http://example.com/pricing
Rails App 2 (our real App) serves:
http://example.com/account
http://example.com/store
http://example.com/listings
We use ruby 1.9.2, ruby on rails, refinery cms, apache and passenger.

If you're using Passenger, check out the Deploying to a sub URI portion of the manual - it's quite simple to set up an app on a sub-URI. You may need to set config.action_controller.relative_url_root in your app configuration, as well.
Edit: I misread the question; not one app per URI, but one app serving some (but not all) endpoints. This is actually moderately easy to do with some basic rewrites, as well.
Deploy your Rails app to, let's say, /railsapp (but without setting relative_url_root). Now, in .htaccess:
RewriteRule ^account/(.*)$ railsapp/account/$1 [L]
This will internally remap /account/* to /railsapp/account/*, so as long as you set up a rewrite per path your Rails app handles, it should work fine.

Subdomains make it easier (thus why most sites have shop.example.com), but you could probably use rewrite rules with name based virtual host routing. How exactly to do that I'm not sure. More of a Apache rewrite question for SuperUser.
A word of warning if you are using SSL you might have issues arise.

You could set it up to first hit one app where you expect most URLs would work and if it 404s you could instruct it to try the other app next, though this will be slower than routing per route but it will work without having to hardcode a route for every page that is created on say, Refinery CMS.

Currently I'm also working on a same kind of CMS. In my case also I need multiple sub domains, like
www.test1.mydomain.com
www.test2.mydomain.com
www.test3.mydomain.com
www.test4.mydomain.com
here is what I did
in rails 3 (if you are on rails3) you can get the sub domain by using request object. (If you are on rails 2.x you can use sub domain_fu plugin)
In my case I have used a before filter to get the sub domain, after that I load the site according to the sub domain
For development use the following public domain "lvh.me"
http://tbaggery.com/2010/03/04/smack-a-ho-st.html
this was very useful for me http://railscasts.com/episodes/221-subdomains-in-rails-3
let users have their domains forwarded to your subdomain (with masking)
ex : www.clientdomain.com --> http://client.mydomain.com
hope this helps
cheers
sameera

Related

Is it possible to have Rails mask blog.mydomain.com as mydomain.com/blog?

I'd like to install a Wordpress blog that is associated with my domain. I am running a Ruby on Rails app on that domain so I know the easiest thing to do is set up a subdomain for the blog. However, I'd like to keep everything under the same roof, as it were.
How would I go about using Rails/Rack to serve blog.mydomain.com when going to mydomain.com/blog? My first thought was to perform some kind of mask or scrape the other domain and present the HTML as coming from /blog.
The app is running on Heroku, and I'm pretty sure how I would take care of this one an Apache server with .htaccess file (similar to what Wordpress does with permalinks), but I'm not sure how to accomplish this with the tools I have on hand.
Thanks.
You could use rack-rewrite to redirect requests to mydomain.com/blog to blog.mydomain.com.

Need to link WP Blog with Rails App on Heroku

I have a client who wants to migrate his Rails app to Heroku. However the client also has a blog associated with his domain that runs on WordPress. Currently, the WordPress blog is running happily alongside the Rails app, but once we migrate to Heroku, that clearly won't be possible.
The url for the app is like http://mydomain.com, and the url for the blog is like http://mydomain/blog.
I realize that the best long-term solution is to redo the blog in a Rails format like Toto or Jekyll. But in the short term, what is the best way to continue hosting the WP blog where it is (or somewhere) but use Heroku to run the app? The client doesn't want the blog to be on a subdomain, but to remain at mydomain/blog for SEO reasons and also since there is traffic to the blog. I have two ideas:
Use rack_rewrite or refraction (or just a regular old 301 and Apache mod_rewrite) on the old (non-Heroku) server to redirect the main url from the old site to Heroku. In this case, I can just leave the Wordpress blog running happily where it is. I think?? Is there a reason to choose one of those options (rack_rewrite, refraction, or mod_rewrite) over the others if I do it this way?
Switch the DNS info to point to the Heroku site, and then use a 301 redirect from the blog to the old site. But then I'll have to get the old (non-Heroku) site on a subdomain and use some kind of rewrite rules anyway so it looks like it isn't a subdomain.
Are either of these approaches preferable, or is there another way to do it that's easier that I'm missing?
The only tenable long term/scalable solution would be to host the blog permanently on a sub-domain or different domain and add a redirect from mydomain.com/blog to the new location (ie: blog.mydomain.com).
You would need a single server running a front-end like Apache/nginx on mydomain.com to serve up mixed back-ends like Rails and Wordpress and that is not possible on Heroku.
Sadly, this is where you need to dig in as a consultant and be stern with your client about the technical limitations.
Why does you client want to migrate to Heroku? Is there a larger goal behind that you could accomplish with different hosting where you control the front-end and can mix in different back ends?
Another solution is to set heroku to http://app.example.com, and Wordpress to http://example.com. You put your Wordpress-landing page in the root , and blog on /blog. When the user click "login" or "signup" on the landing-page, they're linked to the heroku-app.
This will be optimal in a SEO-perspective, but require some DNS-knowledge.
Winfield's answer is not correct. You can run a reverse proxy on your rack server (via Heroku) to direct to the blog, wherever it may be.
See https://github.com/jaswope/rack-reverse-proxy
After you install the gem and set up your app according to the docs, your ./config.ru file will have something like this:
use Rack::ReverseProxy do
reverse_proxy(/^\/blog(\/.*)$/,
'http://<app-name>.herokuapp.com$1',
opts = {:preserve_host => true})
end

Mapping multiple domain names to different resources in a Rails app

The rails app I have allows users to manage holiday homes. Each property has it's own
"website/homepage" within my app and a user can tweak the content, it works well,
quite pleased so far. Typical rails approach to the resources so the URLs to a particular property look like this for the "homepage" of a particular property.
localhost:3000/properties/1/
then
localhost:3000/properties/1/full_details
localhost:3000/properties/1/price_list
etc
Requirement is to map a domain name e.g. www.chalet-yeti.com and have it resolve (rewrite?) to localhost:3000/properties/1/
like so also...
www.chalet-yeti.com/full_details -> localhost:3000/properties/1/full_details
The next user adds a property and I register a new name on their behalf and I'd like to do this of course..
www.apartment-marie.com -> localhost:3000/properties/2/
Is this possible/advisable/doable in the same rails app? So far solutions have ranged from "why would you do that" to variations on "use mod_proxy / mod_rewrite / virtual_host config". In case it matters the app runs under apache and passenger on my server.
I don't want to pre-empt an answer but most people so far seem to point to apache configuration and most say what I'm attempting is not impossible / inadvisable. Really hope someone could at least point me in the right direction as I've been head scratching all morning. Out of my comfort zone here and I'm hoping I can launch my app and haven't spent six weeks building a white elephant! Unless I can do this URL thing, it's dead!
http://37signals.com/svn/posts/1512-how-to-do-basecamp-style-subdomains-in-rails
This is what you want. Don't mess with apache for that. It doesn't scale to hundreds of domains and it's prone to breakage.
Within Rails, you should think of the requests coming just to a URI, without a host name section. That is, instead of localhost:3000/properties/1/full_details you need to think of /properties/1/full_details. The localhost:3000 part is just to get the request to Mongrel during the development process.
So what you really want is to take the request as it is received by the HTTPd (Apache, in your case) and extract some information to construct the request which is given to Rails.
mod_rewrite, which is an Apache module, is the sane way to do this.
You need to ensure that the same virtual host which runs your Rails application accepts requests for all the domain names you're using.
Then you can use mod_rewrite to do something like this:
RewriteCond %{HTTP_HOST} ^(www.)?chalet-yeti\.com$
RewriteRule ^(.*)$ /properties/1/$1 [L]
This will take every request to the host chalet-yeti.com (or www.chalet-yeti.com) and hand them to Rails as "/properties/1/$1" (where the $1 is any additional path, like full_details).
You'll need a block like that for each of your domains, but that's just two lines in your Apache configuration. Unless you're doing hundreds of domains, it should be tolerable, right?

Dynamically Create Virtual Hosts with Rails, Nginx?

I really like Basecamp's idiom of "dynamically" creating custom virtual hosts for clients -- for instance, once a company has signed up they may quickly login to a special URL like:
https://mystartup.basecamphq.com/
--which I think is really neat, it segregates multiple organizations nicely within a single application. My question is: assuming I've got control of a given domain, is there an easy way to do this kind of black magic with Rails and Nginx -- that is, to dynamically create a virtual host?
How to do Basecamp-style subdomains in Rails
Also:
Subdomain accounts with Ruby on Rails explained
Most cases you are not truly creating a virtual host. You created a subdomain one time that then accepts ANY sub-domain off of it and you pipe it to your back end for processing (404, 302, or 200).
do a search on "nginx wildcard subdomain". The results from slicehost are usually very helpful.

Account based lookup in ASP.NET

I'm looking at using ASP.NET for a new SaaS service, but for the love of me I can't seem to figure out how to do account lookups based on subdomains like most SaaS applications (e.g. 37Signals) do.
For example, if I offer yourname.mysite.com, then how would I use ASP.NET (MVC specifically) to extract the subdomain so I can load the right template (displaying your company's name and the like)? Can it be done with regular routing?
This seems to be a common thing in SaaS so there has to be an easy way to do it in ASP.NET; I know there are plugins that do it for other frameworks like Ruby on Rails.
This works for me:
//--------------------------------------------------------------------------------------------------------------------------
public string GetSubDomain()
{
string SubDomain = "";
if (Request.Url.HostNameType == UriHostNameType.Dns)
SubDomain = Regex.Replace(Request.Url.Host, "((.*)(\\..*){2})|(.*)", "$2");
if (SubDomain.Length == 0)
SubDomain = "www";
return SubDomain;
}
I'm assuming that you would like to handle multiple accounts within the same web application rather than building separate sites using the tools in IIS. In our work, we started out creating a new web site for each subdomain but have found that this approach doesn't scale well - especially when you release an update and then have to modify dozens of sites! Thus, I do recommend this approach rather than the server-oriented techniques suggested above based on several years worth of experience doing exactly what you propose.
The code above just makes sure that this is a fully formed URL (rather, say, than an IP address) and returns the subdomain. It has worked well for us in a fairly high-volume environment.
You should be able to pick this up from the ServerVariables collection, but first you need to configure IIS and DNS to work correctly. So you know 37Signals probably use Apache or another open source, unix web server. On Apache this is referred to as VirtualHosting.
To do this with IIS you would need to create a new DNS entry (create a CNAME yourname.mysite.com to application.mysite.com) for each domain that points to your application in IIS (application.mysite.com).
You then create a host header entry in the IIS application (application.mysite.com) that will accept the header yourname.mysite.com. Users will actually hit application.mysite,com but the address is the custom subdomain. You then access the ServerVariables collection to get the value to decide on how to customize the site.
Note: there are several alternative implementations you could follow depending on requirements.
Handle the host header processing at a hardware load balancer (more likely 37Signals do this, than rely on the web server), and create a custom HTTP header to pass to the web application.
Create a new web application and host header for each individual application. This is probably an inefficient implementation for a large number of users, but could offer better isolation and security for some people.
You need to configure your DNS to support wildcard subdomains. It can be done by adding an A record pointing to your IP address, like this:
* A 1.2.3.4
Once its done, whatever you type before your domain will be sent to your root domain, where you can get by splitting the HTTP_HOST server variable, like the user buggs said above:
string user = HttpContext.Request.ServerVariables["HTTP_HOST"].Split(".")
//use the user variable to query the database for specific data
PS. If you are using a shared hosting you're probably going to have to by a Unique IP addon from them, since it's mandatory for the wildcard domains to work. If you're using a dedicated hosting you already have your own IP.
The way I have done it is with HttpContext.Request.ServerVariables["HTTP_HOST"].Split(".").
Let me know if you need more help.

Resources