Ruby on Rails
HowtoDeployMoreThanOneRailsAppOnOneMachine
There are several ways to host multiple rails apps on one server; if they are small and there is no conflict between their name spaces you might consider merging them into one “super app”—but for anything larger than toy apps, this is simply asking for trouble,
Deployment in separate folders for each app on one Apache server
WikiGardening required. This section may be out of date, make sure you read the surrounding sections too.
Suppose you’d rather have various Rails apps running on your machine in different folders, with URLs like:
<pre>
<a href="http://www.myhost.org/appOne/">http://www.myhost.org/appOne/</a>...
<a href="http://www.myhost.org/appTwo/">http://www.myhost.org/appTwo/</a>...
</pre>
This is very easy if you are using Apache & mod_rewrite.
- Put a symlink to each application’s directory in your document root (e.g., “
ln -s /opt/rails/appOne /var/www/html/appOne” and so forth for each application)
- In each application’s
.../appName/public/.htaccess file, add the line “RewriteBase /appName” right after the “RewriteEngine On” line.
- In your main
httpd.conf file do something like this:<pre>
<VirtualHost *>
ServerName <a href="http://www.myhost.org">www.myhost.org</a>
DocumentRoot /var/www/html/
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/appOne/public
RewriteRule ^/appOne(/.*)?$ /appOne/public$1
<Directory /var/www/html/appOne/public/>
Options ExecCGI FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
RewriteCond %{REQUEST_URI} !^/appTwo/public
RewriteRule ^/appTwo(/.*)?$ /appTwo/public$1
<Directory /var/www/html/appTwo/public/>
Options ExecCGI FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
Note that this differs from the normal in three regards:
- first, the document root is “normal” (not specific to rails),
- and secondly there are multiple
<Directory> blocks (one for each rails application),
- and finally there is a rewrite rule preceding each
<Directory> block to route traffic for that application.
As requests come in, they are rewriiten based on the appName and then handled normally.
Even Simpler Method
- Follow the first step from above (i.e. create symlinks to the public folders of each of the rail applications)
- Then in the main
httpd.conf, do this:
<pre>
<VirtualHost *:80>
ServerName localhost
DocumentRoot /Users/bob/Sites/
RewriteEngine On
<Directory /Users/bob/Sites/>
Options FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
This is using Rails version 0.12.1, Apache 2.0, and OSX 10.4
Multiple Rails Apps On Windows with Apache 2.0 and Rails 0.13
Similar to the other instructions, but with some minor changes. Symbolic links don’t work well on Windows servers unless you use Junctions, but it turns out that it’s not needed.
- Make a folder for your web pages
<pre>c:\web\apps</pre>
- Place each rails directory under this folder
<pre>
c:\web\apps\
c:\web\apps\blog
c:\web\apps\blog\public
....
c:\web\apps\todolist\
c:\web\apps\todolist\public
.....
</pre>
- Place this at the end of your Apache configuration
<pre>
Alias /blog "c:/web/apps/blog/public"
- uncomment next line if you have enabled fastcgi
#FastCgiServer c:/web/apps/blog/public/dispatch.fcgi -idle-timeout 120 -initial-env RAILS_ENV=production -processes 1
<Directory c:/web/apps/blog/public>
Options ExecCGI FollowSymlinks
AllowOverride All
Alias /todo “c:/web/apps/todo/public”
- uncomment next line if you have enabled fastcgi
#FastCgiServer c:/web/apps/todo/public/dispatch.fcgi -idle-timeout 120 -initial-env RAILS_ENV=production -processes 1
<Directory c:/web/apps/todo/public>
Options ExecCGI FollowSymlinks
AllowOverride All
- Next, you’ll have to edit the .htaccess file in each Rails app. You’re going to need to change the dispatch.cgi to dispatch.fcgi (if you’re using fast-cgi) but more importantly, you’re going to need to add
<pre>
RewriteBase /blog
</pre>
to your /blog app and then do the same for the /todo app
- Do the same fo the other application, making sure to specify the paths appropriately.
- NOTE: If you want the blog app to reside at /blog and the todo app to reside at /, use the following RewriteCond and RewriteRule in httpd.conf (in addition to RewriteBase in .htaccess):
<pre>
<VirtualHost *:80>
ServerName mybox.company.com
DocumentRoot c:/web/apps/
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/todo/public
RewriteCond %{REQUEST_URI} !^/blog
RewriteRule ^(.*)?$ /todo/public$1
<Directory c:/web/apps/todo/public>
…
RewriteCond %{REQUEST_URI} !^/blog/public
RewriteRule ^/blog(/.*)?$ /blog/public$1
<Directory c:/web/apps/blog/public>
…
- Be sure to update your environment files if you are using this for production! Also be sure to make sure you know HowtoChangeSessionOptions because you could end up with session errors if you’re not careful.
Add this to the end of your config/environment.rb file
<pre>
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update(:prefix => 'blog.')
</pre>
and do the same for the todolist application.
- At that point, everything should work as expected. You should be able to do http://mybox.company.com/blog/ and pull up the blog application to ensure that you don’t have problems loading sessions.
- Make sure that you have the very latest dispatch.fcgi file and the latest .htaccess file. Don’t waste hours trying to make this work like I did only to find out you have the wrong files.
Han Holl rails.conf
<pre>
- Directory based Rails apache configuration without per directory mod_rewrite
- Two global replaces (in the right order) should suffice to relocate
- This file can be dropped in /etc/httpd/conf.d as rails.conf — no need to touch httpd.conf
- Can co-exist with other parts of a website and other rails applications
alias /rails /var/www/rails/public
<IfModule !mod_fastcgi.c>
LoadModule fastcgi_module modules/mod_fastcgi.so
FastCgiServer /var/www/rails/public/dispatch.fcgi -socket /var/tmp/rails.socket
RewriteLog /var/log/rewrite.log
RewriteLogLevel 5
RewriteEngine On
- Skip rest of rewrite if url doesn’t start with /rails
- Yes, S=14 is rather fragile, but it’s the best we can do at this time
RewriteCond %{REQUEST_URI} !^/rails/?
RewriteRule .* – [S=15]
- Skip rest of rewrite if there is no controller
- Use PT to let mod_alias do the remapping
RewriteCond {REQUEST_URI} !^/rails(/fcgi/|/mruby/|/)([-a-zA-Z0-9]+)/
RewriteRule .* – [S=14,PT]
RewriteCond %{REQUESTURI} ^/rails(/fcgi/|/mruby/|/)([-_a-zA-Z0-9]+)/
RewriteCond /var/www/rails/public/../app/controllers/2_controller.rb !-f
RewriteRule .* – [S=13,PT]
- Remove /rails from URL
RewriteRule ^/rails(.*) $1
- Force fcgi
RewriteRule ^/fcgi/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)/([-a-zA-Z0-9.]+)$ /var/www/rails/public/dispatch.fcgi?controller=$1&action=$2&id=$3 [L,QSA]
RewriteRule ^/fcgi/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)$ /var/www/rails/public/dispatch.fcgi?controller=$1&action=$2 [L,QSA]
RewriteRule ^/fcgi/([-a-zA-Z0-9]+)/?$ /var/www/rails/public/dispatch.fcgi?controller=$1&action=sql [L,QSA]
RewriteRule ^/fcgi.* /var/www/rails/public/dispatch.fcgi?controller=dps&action=sql [L,QSA]
- Force mod_ruby
RewriteRule ^/mruby/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)/([-a-zA-Z0-9.]+)$ /var/www/rails/public/dispatch.rb?controller=$1&action=$2&id=$3 [L,QSA]
RewriteRule ^/mruby/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)$ /var/www/rails/public/dispatch.rb?controller=$1&action=$2 [L,QSA]
RewriteRule ^/mruby/([-a-zA-Z0-9]+)/?$ /var/www/rails/public/dispatch.rb?controller=$1&action=sql [L,QSA]
RewriteRule ^/mruby.* /var/www/rails/public/dispatch.rb?controller=dps&action=sql [L,QSA]
- Default rewriting rules. Change extension from .cgi to .fcgi to switch to FCGI and to .rb to switch to mod_ruby
RewriteRule ^/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)/([-a-zA-Z0-9.]+)$ /var/www/rails/public/dispatch.cgi?controller=$1&action=$2&id=$3 [L,QSA]
RewriteRule ^/([-a-zA-Z0-9]+)/([-a-zA-Z0-9]+)$ /var/www/rails/public/dispatch.cgi?controller=$1&action=$2 [L,QSA]
RewriteRule ^/([-a-zA-Z0-9]+)/$ /var/www/rails/public/dispatch.cgi?controller=$1&action=sql [L,QSA]
RewriteRule .* /var/www/rails/public/dispatch.cgi?controller=sql&action=show [L,QSA]
<Directory /var/www/rails/public>
AllowOverride none
Order allow,deny
Allow from all
# General Apache options
AddHandler fastcgi-script .fcgi
AddHandler cgi-script .cgi
Options +FollowSymLinks +ExecCGI
# Remember to set RubySafeLevel 0 in httpd.conf
RubySafeLevel 0
RubyRequire apache/ruby-run
SetHandler ruby-object
RubyHandler Apache::RubyRun.instance
# You can also point these error messages to a controller/action
ErrorDocument 500 /rails/500.html
ErrorDocument 404 /rails/404.html
Looks interesting but …
Apache will then automatically load this file? Also I’m not that proficient in configuring Apache and how once I’m using this .conf file what my app directory structure should look like. At this point I don’t have a public dir in /var/www/rails so I’ll create one but then what goes in it?
category: Howto