The basic idea is to setup one or more instances of Mongrel to handle the Ruby/Rails content and have Apache handle static content. In addition, Apache will act as a proxy and load-balance the request to Mongrel. The best resource I found was a page on Mongrel's site titled Apache Best Practice Deployment.
Here's the basics of how I set it up:
Software:
In my case, I have one main development machine, one database server and a combined web/application server.
Pre-requisites: Ruby 1.8.5 or later, Ruby Gems and Capistrano
$ gem install deamons gem_plugin mongrel mongrel_cluster --include-dependencies
$ mongrel_rails cluster::configure -N 3 -e production -p 9000 -a 127.0.0.1 -c /path/to/current/on/application/server
This creates mongrel_cluster.yml in your config directory. The -N 3 option tells Mongrel to setup three instances. The -e option tells Mongrel that these instances will be running in production mode (aka RAILS_ENV='production'). The -p option specifies the base port number. Since we're creating three instances, they will be running on ports 9000, 9001 and 9002. The -a option specifies the address Mongrel should bind to, the localhost in this case. The final option, -c, tells Mongrel to change to the specified directory before starting up. Since this cluster configuration corresponds to our production server, the specified path should be the actual path to the Rails application on the server. Assuming you're using Capistrano, this should be the current symlink for the application.
You will also need to tell Capistrano to use the Mongrel recipes for deployment. Edit deploy.rb and add the following to the top:
require 'mongrel_cluster/recipes'
You also need to specify the name of the Mongrel configuration file in deploy.rb, so add the following somewhere after setting deploy_to:
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml
As of this writing, Capistrano 2.0 is available. One of the new features in Capistrano 2 is the concept of namespaces for tasks. Unfortunately, namespaces change the technique used to override a task. Mongrel 1.0.1 has not been converted to Capistrano 2, so the default recipes that come with Mongrel need to be tweaked. Specifically, I copied the restart task from mongrel_cluster-1.0.2/lib/mongrel_cluster/recipes.rb into my and my deploy.rb and made one small modification:
desc <<-DESC Restart the Mongrel processes on the app server by calling restart_mongrel_cluster. DESC deploy.task :restart, :roles => :app do restart_mongrel_cluster end
Pre-requisites: Ruby 1.8.5 or later, Ruby Gems and Capistrano
$ gem install deamons gem_plugin mongrel mongrel_cluster --include-dependencies
Make certain mod_proxy and mod_proxy_balancer are both setup. mod_proxy_balancer requires Apache 2.1 or later. Create a load balancer configuration file for the Mongrel cluster and place this somewhere in the Apache configuration tree. Here's a sample, which I called myappname.proxy_cluster.conf:
BalancerMember http://127.0.0.1:9000 BalancerMember http://127.0.0.1:9001 BalancerMember http://127.0.0.1:9002
This tells apache to load-balance requests for mongrel_cluster to the three Mongrel instances we setup earlier. Include this in the main httpd.conf file. Then create a virtual host entry for the server as well:
ServerName myservername.com DocumentRoot /var/webapps/myapp/current/public Options FollowSymLinks Order deny, allow Allow from all Options FollowSymLinks AllowOverride None ErrorLog /var/log/apache/myapp-error.log CustomLog /var/log/apache/myapp-access.log RewriteEngine On # Uncomment for rewrite debugging #RewriteLog logs/myapp_rewrite.log #RewriteLogLevel 9 # Check for maintenance file and redirect all requests # ( this is for use with Capistrano's disable_web task ) # The -f option tests for the existence of the specified file. # If it exists, forward all requests to the maintenance page # and stop processing. RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f RewriteCond %{SCRIPT_FILENAME} !maintenance.html RewriteRule ^.*$ /system/maintenance.html [L] # Rewrite to check for Rails cached page RewriteRule ^([^.]+)$ $1.html [QSA] # Redirect all non-static requests to cluster. # Again, the -f tests for the existence of the specified file. # If the file does NOT exist, forward the request the load-balanced # Mongrel cluster and stop processing rules. RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L] # Deflate AddOutputFilterByType DEFLATE text/html text/plain text/css # ... text/xml application/xml application/xhtml+xml text/javascript BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
The one secret piece is the directory entry for "/var/webapps/myapp". In most of the standard Apache installs I have seen, the default configuration includes a Directory entry for "/" that disables everything. A typical Capistrano deployment creates current as a symlink to releases/XXX. In my situation, Apache was unable to navigate into current, because of the top-level rule for "/" that explicitly forbid following symbolic links. The entry for "/var/webapps/myapp" is the work-around.
Recent comments
1 year 40 weeks ago