Thu Jan 24, 2008
Running Rails Apps in a Subdirectory
Rails likes to be run in the top root directory of a web site, such as domain.com/. It doesn't play very nicely if you try to deploy an app in a subdirectory such as domain.com/myrailsapp. Nonetheless, sometimes you just want to deploy a basic app within its own folder under your current domain. I managed to cobble together a simple solution taking bits and pieces from others who have gone down a similar path. I don't take credit for this method, I am just writing down what I learned in hopes that it might helps someone others caught in a similar predicament. This solution isn't enterprise level by any means. It doesn't leverage all the wonderful potential of using a mongrel cluster, load balancing, etc. One nice perk of this method is it doesn't require root access which is ideal for those using shared hosting. There's no changes to the httpd.conf file. Everything is configured on the development side.
Here's how I do it. Feel free to adjust it to your needs:
I set up my Rails apps in my root directory: /home/user/myapp . I like to keep my apps out of the public directory just in case things go terribly wrong. Last thing you want it someone downloading your database.yml file. Next, set up a rewrite condition in a .htaccess file within the web servers public directory (/home/username/public_html on my server):
RewriteCond %{HTTP_HOST} ^domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.domain.com$
RewriteRule ^myapp http://127.0.0.1:8000%{REQUEST_URI} [P,QSA,L]
This basically tells Apache that any requests for domain.com/myapp should be forwarded to port 8000 which is where my Mongrel server is listening and ready to serve the Rails app. You'll probably have to change the port number for your Mongrel server.
Now if you have your Mongrel server running for your app (I'm not going to address that, there are plenty resources for setting up Mongrel) and you try to go to domain.com/myapp it will probably work (that is, be served by Mongrel and not Apache) but will most likely throw an error. The next step is to open the config/environment.rb file and add this line to the very end:
ActionController::AbstractRequest.relative_url_root = "/myapp"
This tells Rails to append /myapp to all the urls it creates in your views and controller. Without this, every link would be broken within your app. So you if fire up the browser you should be able to move though your app like normal (you may need to restart Mongrel since you made changed to your app). But you'll notice something is missing: your stylesheets, images and javascripts won't be loaded. Basically Rails isn't able to access anything from within the Rails public folder. This problem stumped me for a long while but the solution is quite simple:
Go to the public directory and create a symbolic link by typing:
ln -s . myapp
And that's it. Your app should work like normal from within the subdirectory. If you are using a Cpanel server that supports Rails, it will handle creating the Rails app, the .htaccess rewrite, and setting up the Mongrel process. All you have to worry about is the environment.rb edit and the symbolic link. Again, this isn't a scalable or robust solution by any means. I haven't tested it very extensively so there may be other ramifications that I just haven't come across. It also forces everything through Mongrel, including static content like Javascript, images, css, etc. Ideally we want Mongrel to handle the dynamic content and Apache to continue to serve out the static content. As I experiment with this setup, I plan on adjusting the rewrite rules to accommodate this. But for now, use it at your own peril. •