Rails with Apache MPM worker
The existing instructions for Typo on FreeBSD presume that you’re running lighttpd and Apache httpd with mod_proxy. This is unnecessary and, generally speaking, more complicated than what most people need. It turns out you can serve your Rails app, legacy PHP pages and static content just fine with just one webserver installed. This can also help save memory (my own motivation), by running PHP as a FastCGI process rather than embedding it in every Apache MPM prefork process.
It seems like many users aren’t aware that there is any option beside MPM prefork for Apache httpd. Starting with Apache httpd 2 you can choose different multi-processing models. One of these is MPM worker, which keeps not only multiple processes, but also uses several threads to handle requests.
Threads complicate matters with things that are not typically thread-safe like mod_php, mod_perl, and many other programming language Apache modules. Luckily FastCGI can move this work outside of the httpd process where it can be handled outside of these threading concerns.
Before I wander into the exact details of configuring this setup, a word about performance: Super. MPM worker does a fabulous job serving static and dynamic content quickly. In addition, memory consumption is much easier to control since the FastCGI processes associated with each language or Rails application can be independently controlled and tuned to the traffic they’re seeing.
Installing the Pieces
I put the following into my /etc/make.conf
to make sure the components are built correctly:
WITH_APACHE2=YES
WITH_MPM=worker
WITH_KQUEUE_SUPPORT=YES
WITH_FASTCGI=YES
Next, the correct ports have to be built. The packages are listed below along with their origin (that is, where to find them in the FreeBSD ports collection). Building the things below with the options above will be different on other systems.
Package | Origin |
---|---|
apache-worker-2.0.54_4 | www/apache2 |
rubygem-rails-0.13.1 | www/rubygems-rails |
mod_fastcgi-2.4.2 | www/mod_fastcgi |
ruby18-fcgi-0.8.6 | www/ruby-fcgi |
ruby18-sqlite-2.2.3 | databases/ruby-sqlite |
ruby18-postgres-0.7.1_2 | databases/ruby-postgres |
ruby18-mysql-2.6 | databases/ruby-mysql |
You only need the database package relevant to the database you want to be using; which one you should not use is a rant for another day, today I’m going to use sqlite. There may be newer versions of these packages available by the time you read this.
For this example, we’ll unzip/untar the latest typo release into /usr/local/www/data.
Configuring the components
First, I’m going to get the Typo install configured. This is simply building the database with sudo -u www sqlite db/typo.sqlite.db < db/schema.sqlite.sql
and then changing my config/database.yml to contain:
login: &login
adapter: sqlite
dbfile: db/typo.sqlite.db
development:
<<: *login
test:
<<: *login
production:
<<: *login
A quick run with script/server
will indicate if things are working correctly with the Rails application. I had to comment out a line in config/environment.rb to get it to run (and have filed a bug about it).
I also check at this point if public/dispatch.fcgi
will run correctly from within Apache httpd. Generally the PATH used by Apache httpd will not include the ruby executable, so I change the /usr/bin/env ruby
at the top of public/dispatch.fcgi
to /usr/local/bin/ruby
.
Now I’ll configure Apache httpd. The default values for MPM worker are quite reasonable, so I’ll leave them alone. You’ll find them near the text <IfModule worker.c>
along with a comment about what the settings do.
Setting ServerName
is usually a good idea right about now. Remember that this needs to be a real name that points at this server.
In order for Apache to use the FastCGI module, it’ll need to know that I want it to be loaded. At the end of all the lines that start with LoadModule
we’ll want to add the FastCGI module with:
LoadModule fastcgi_module libexec/apache2/mod_fastcgi.so
Next, move the DocumentRoot
into Rails application by changing it to "/usr/local/www/data/typo/public"
Lastly, after the line with DocumentRoot
I add lines specific to the FastCGI configuration and the permissions we want:
<IfModule mod_fastcgi.c>
FastCgiIpcDir /tmp/fcgi_ipc/
FastCgiServer /usr/local/www/data/typo/public/dispatch.fcgi -idle-timeout 120 -initial-env RAILS_ENV=production -processes 2
FastCgiConfig -idle-timeout 120 -initial-env RAILS_ENV=production -restart
AddHandler fastcgi-script fcgi fcgi fpl
</IfModule>
<Directory "/usr/local/www/data/typo/public">
AllowOverride All
Options ExecCGI
</Directory>
The critical line in there is the FastCgiServer
line that Scott Laird has written about in some detail on his blog.
And we’re off…
Now I just run apachectl start
as root and I’m up and running.
No comments:
Post a Comment