This blog is no longer updated. We have moved to Please update your bookmarks.

Ruby on Rails served by Lighttpd behind reverse proxy on Apache 2.0

Summary: If you want Apache 2.0, PHP and Rails, do yourself a favor, use reverse proxy and Lighttpd.

After few unproductive hours spent fighting FastCGI and Apache 2.0 and far too much coffee drunk, I was forced to make a decision.

Our Apache server hosts PHP applications for a dozen of our clients and needs to work very stable and uninterruptedly. There is also an urgent need to host Rails applications on the same server, namely the same IP and in some cases simultaneously in the same URL namespace with PHP applications. This is a bit tricky but useful setup if you take the possibilities into account.

O.K. Lets get to work. We have the Apache server (btw. on Debian, so we will do it Debian way). We want to minimize changes in its configuration. We definitely need to enable mod_proxy:
a2enmod proxy

Then we need to configure it, so we create file /etc/apache2/sites-available/lighty-rproxy and put some date in it:

<VirtualHost *>

<Proxy *>
Order deny,allow
Allow from all

<Location />
ProxyPass http://localhost:81/
ProxyPassReverse http://localhost:81/

ProxyPreserveHost On

Here we enable this vhost:
a2ensite lighty-rproxy
/etc/init.d/apache2 force-reload

If you now point your browser to configured domain (we use famous you should see information about "Bad Gateway". Don't panic. We have all under control. Inhale... Exhale... Yes. Like this.

What we just saw was reaction of Apache which wanted to redirect everything inside to another http server on the same host (localhost) but on port 81. So now we need to put something there.

We install Lighttpd:
apt-get install lighttpd
and configure it. Below are excerpts from /etc/lighttpd/lighttpd.conf we need to change. First we enable mod_rewrite and mod_redirect:
server.modules              = (
# "mod_status",
# "mod_evhost",
# "mod_compress",
# "mod_usertrack",
# "mod_rrdtool",
# "mod_webdav",
# "mod_expire",
# "mod_flv_streaming",
# "mod_evasive"

Then we bind lighty to localhost:81 to correspond to Apache configuration:
## bind to port (default: 80)
server.port = 81

## bind to localhost only (default: all interfaces)
#server.bind = "localhost"

In file /etc/lighttpd/conf-available we have to comment fastcgi server definition for php (unless we have php4-cgi installed) and enable fastcgi in Lighty by invoking:
lighty-enable-mod fastcgi

Last thing we need is our humble vhost configuration for Rails app which sits in /etc/lighttpd/conf-available/11-rails-app.conf and looks like this: = "/home/necro/rails/linkpro"

$HTTP["host"] == "" {
server.document-root = + "/public"
url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" )
server.error-handler-404 = "/dispatch.fcgi"
fastcgi.server = ( ".fcgi" =>
( "localhost" =>
( "min-procs" => 2,
"max-procs" => 2,
"socket" => "/tmp/app.fcgi.socket",
"bin-path" => + "/public/dispatch.fcgi",
"bin-environment" => ( "RAILS_ENV" => "development" )

As you can see this configuration is pretty simple but works and is a good start for more complicated setups where you separate application server from http server or create other sophisticated configurations. Just remember to properly set rights to log and tmp directories in your Rails app. Lighty needs to write to them. I overlooked this at first and lost some time so you don't have to.

Feedback strongly appreciated.


At 12:55 PM CEST, Blogger josef said...

very cool.
i have the same problem.
I will try this solutions soon.
nice work.


Prześlij komentarz

Links to this post:

Utwórz link

<< Home