Ruby on Rails
HowToInstallLighttpdOnFreeBsdViaProxyPassThroughFromApache

The Scenario

You have a VirtualHost kind of Apache configuration that works great for your legacy PHP applications. Now you’ve developed a smashing Rails app that (possibly) uses both SSL and non-SSL links (i.e. http:// and https://). Either you’ve heard how cool Lighttpd is, or you’ve run out of options with Apache and need a stable, speedy FastCGI? server to dish out your Rails application. You don’t want to just tear down Apache because it’s serving its purpose just fine right now. Instead, you’d like to pipe traffic for one particular VirtualHost (i.e. your Rails app) through Apache and directly to Lighttpd. You’ll let Apache deal with the SSL stuff (it does just fine in that area) and you’ll let Lighttpd handle the FastCGI? stuff (it excels in that area).

Assumptions

  1. You’re running FreeBSD, or you know how to convert these FreeBSD-centric instructions to your operating system of choice.
  2. You’ve already installed FastCGI? from ports, and installed the C version of the FastCGI? ruby bindings via gem install fcgi.
  3. Apache has mod_rewrite and mod_proxy
  4. If you’re going to use SSL:
    1. Apache has mod_ssl, and your system has openssl installed.
    2. You already know how to create your CSR and you’ve generated an encrypted server key and you’ve applied for and downloaded an SSL certificate somewhere (e.g. godaddy.com). NOTE: Your secure VirtualHost must have its own IP address in order for the secure certificate to work. It’s ok if it’s on the same box as other VirtualHosts, but if that’s the case, then that box must have an IP alias set up so that your secure site can have its very own IP address (otherwise the browser will do a DNS lookup on the server IP address and fail to confirm that the server is indeed the secure server it claims to be). For more information on setting up a secure certificate, see StarFieldTech’s Enrollment Guide

Step 1: Install Lighttpd

Make sure you’ve got the latest ports from CVS before following these directions. As of this writing, the most up-to-date lighttpd is 1.3.14.

cd /usr/ports/www/lighttpd
make install

# Add lighttpd_enable="YES" to rc.conf
emacs /etc/rc.conf

cd /usr/local/etc
cp lighttpd.conf.sample lighttpd.conf

touch /var/log/lighttpd.access.log
touch /var/log/lighttpd.error.log
chown www:www /var/log/lighttpd*.log

You can now start and stop your fledgling Lighttpd server by:

cd /usr/local/etc/rc.d
./lighttpd.sh start
# -OR-
./lighttpd.sh stop

Step 2: Configure Lighttpd

Edit /usr/local/etc/lighttpd.conf and modify the following:

server.modules = ("mod_access", "mod_accesslog", "mod_fastcgi")
server.document-root = "/home/users/filmfury/public/" 
server.port = 81

fastcgi.server =
( ".fcgi" => ( "localhost" =>
    ( "socket" => "/tmp/rails.socket",                                        
      "bin-path" => "/home/users/filmfury/public/dispatch.fcgi" ),
    (   "socket" => "/tmp/rails2.socket",
        "bin-path" => "/home/users/filmfury/public/dispatch.fcgi" ),
    (   "socket" => "/tmp/rails3.socket",
        "bin-path" => "/home/users/filmfury/public/dispatch.fcgi" )
  )
)

server.indexfiles = ( "dispatch.fcgi", "index.html" )
server.error-handler-404 = "/dispatch.fcgi" 

Those last two lines will direct all traffic that gets sent to Lighttpd to your Rails app to handle. (Since most files will be “404 not found”, the error-handler directive tells Lightppd to go use your Rails application’s dispatcher to handle the request instead of defaulting to the 404 page).

Step 3: Comment or remove all references to FastCGI? in Apache

ed /usr/local/etc/apache/httpd.conf

It may not be necessary to remove all references to FastCGI?, but I did so because I didn’t want Apache to start firing up any of my dispatch.fcgi processes. (Short story: Apache and FastCGI? just wouldn’t work consistently for me. After 4 days of diminishing FastCGI? processes and sales, I threw in the bag and investigated Lighttpd. Hence this How To page.) :)

Step 4: Configure the Apache VirtualHost of Your Choosing

<VirtualHost filmfury.com>
    ServerName filmfury.com
    DocumentRoot /home/users/filmfury/public
    RewriteEngine On 
    ProxyPreserveHost On # Requres Apache 2.0, or a patch (see below)
    RewriteRule ^/(.*) <a href="http://localhost:81/">http://localhost:81/</a>$1 [P,L]
</VirtualHost>

<VirtualHost secure.filmfury.com:443>
    DocumentRoot /home/users/filmfury/public
    ServerName secure.filmfury.com
    ServerAdmin <a href="mailto:admin@mytechsupport.com">admin@mytechsupport.com</a>
    RewriteEngine On
    ProxyPreserveHost On
    RewriteRule ^/(.*) <a href="http://localhost:81/">http://localhost:81/</a>$1 [P,L]
    SSLEngine on
    SSLCertificateFile /usr/local/openssl/certs/filmfury.crt
    SSLCertificateKeyFile /usr/local/openssl/private/filmfury.key
    SSLCertificateChainFile /usr/local/openssl/certs/sf_issuing.crt
    <span class="newWikiWord">SetEnvIf<a href="http://wiki.rubyonrails.org/rails/pages/SetEnvIf">?</a></span> User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
</VirtualHost>

note – this wiki is adding the a href /a to the RewriteRule lines – don’t include in actual config

And that’s about it! Make sure you restart your apache server so that it no longer tries to start up FastCGI? processes (if you had configured it to handle fcgi beforehand). Also, be sure to start (or restart) Lighttpd once your configuration is tip-top.

Enjoy!


Q. What about the ProxyPass? and ProxyPassReverse instructions? I wonder whether they would work as well?

A. I tried that first and couldn’t get it to pass everything forward (it would only pass the root path /). I may have configured something wrong, though, so if anyone has a success story, please do post it here. In any event, RewriteRule with a [P] option simply uses ProxyPass? to do its dirty work, so it shouldn’t make too much of a difference. —canadaduane

Q. What if I’m using Apache 1.3?

A. Using the standard distribution, you can only have one Rails application per instance of Lighttpd, because there is no way for Lighttpd to know which app is being proxy forwarded from Apache. Fear not though; a patch exists with which you can enable the ProxyPreserveHost directive on Apache 1.3.x. Read about it here: ProxyPreserveHost patch for Apache 1.3


I have created these instructions for Debian stable (should work on most linux):

Proxy Lighttpd and Apache2 on Debian Sarge