Mongrel, Apache and Rails on Debian Sarge
Wouldn’t it be cool if you just could
apt-get install mongrel
to set up the great Mongrel web server including a recent version of Ruby and everything else needed to run your Rails applications in a combined Mongrel/Apache load balanced setup on a rock solid and easy-to-maintain Debian Sarge server ?
If the answer is yes, this one is for you.
Not that I don’t like gem
, but on production systems I prefer to have as less package mangement systems as possible ;-)
So the goal is to set up such a server, without doing a single gem install
or ruby setup.rb
. We’ll need to install rubygems
itself, though, since Mongrel depends on it. But as there’s already a debian package for this, there’s nothing to worry about.
Get it
At first, add the following lines to your /etc/apt/sources.list
:
# Ruby 1.8.4, Mongrel, Rake
deb http://debian.jkraemer.net/apt sarge main contrib non-free
#rubygems
deb http://ftp.de.debian.org/debian/ experimental main contrib
The first repository will give you access to the Ruby 1.8.4 and Mongrel debian packages. The second repo is for RubyGems, which Mongrel depends upon. Thanks to the Debian/Ruby Extras team I didn’t need to package this myself :-). Don’t be afraid of the experimental
, we’ll take care that your server stays stable
now:
Add this to /etc/apt/preferences
to give packages from the experimental repository a low priority:
Package: *
Pin: release a=experimental
Pin-Priority: 100
And finally, tell apt that you want to have a stable
system by adding this to /etc/apt/apt.conf
:
APT::Default-Release "stable";
If one of the latter two files doesn’t exist, just create it.
Now, type
apt-get update
apt-get install mongrel
This should pull in Ruby 1.8.4 and some other dependencies automatically.
If you’re not running Apache 2.2 (which usually is the case on Sarge systems), you should apt-get install pen
, too. This will give you the Pen load balancer we’ll use to distribute traffic between multiple Mongrel instances. With Apache 2.2, mod_proxy
can take over Pen’s job, see here for details on this.
Configuration
Mongrel
To give Mongrel a test drive, you should have a Rails application installed somewhere on your server. Each application gets it’s own config file in /etc/mongrel/sites-enabled/
. The name of the config file will be used in start, restart and stop commands, so be sure to choose something meaningful.
Here’s an example config, comments included:
# RAILS_ROOT of your application
dir=/home/webapps/your_application/current
# port the first mongrel instance should listen to, additional instances will use ports above this
port=8100
# number of mongrel instances
servers=3
# port pen will listen on
proxy_port=8001
By default, Mongrel will be run under the www-data
account, just like Apache, too. This can however be overridden by setting the USER
variable in /etc/default/mongrel
to some other account on your server. Just make sure the user has write access to the tmp
and log
directories of your app. Write access to public
is needed for Rails page caching. I usually simply set the owner of these directories to www-data
:
chown -R www-data tmp log public
If you’re using capistrano for deployment, you have to repeat this for tmp
and public
after each deployment (log
is symlinked from shared and therefore will keep it’s permissions during deployments). A custom after_update_code
task might look like this:
task :after_update_code do
sudo "chown -R www-data #{release_path}/public #{release_path}/tmp"
end
Apache
Now we tell Apache to forward requests for your app to the load balancer. You’ll need mod_proxy and mod_rewrite for this. a2enmod {proxy|rewrite}
can be used to enable the modules, in case they aren’t yet.
Here’s a snippet to put into the VirtualHost
section for your app:
# mod_proxy config
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
# send all requests to URIs not corresponding to real files to the load balancer:
RewriteEngine On
RewriteRule ^/$ /index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
# 8001 is the proxy_port from mongrel configuration of your app
RewriteRule .* http://localhost:8001%{REQUEST_URI} [P,QSA]
Run it
You can host any number of applications with this setup, and control them all at once with a simple
/etc/init.d/mongrel {start|stop|reload|restart}
To control a single application, just pass the name of it’s config file as second parameter to the init script:
/etc/init.d/mongrel {start|stop|reload|restart} your_application
The init script will take care of Pen, too. For each application, a Pen process will be launched to distribute requests among the configured port range from port
up to port+servers-1
Automatic startup/shutdown
Run
update-rc.d mongrel defaults
and Mongrel will be started/stopped automatically when you start or shutdown your system.
Finished!
If you freeze Rails and any other dependencies right into your applications (which is a good idea anyway, just think of different applications using different versions of libraries), you’re done now.
/etc/init.d/mongrel start your_application
should fire up Pen and the number of mongrel servers you configured.
For now, this setup is running fine on two production servers. If you encounter any problems, please drop me a line.
As my spare time permits, I’ll try to keep up with the fast development of Mongrel, and provide new packages for new versions.
Comments
Ezra Zygmuntowicz
jk
I'll do my best to keep the packages up to date.