Pound Best Practice Deployment
By Austin GodberPound is a load-balancing reverse HTTP proxy. It can also handle SSL connections. Pound, itself, does not serve content but just acts as a front end to servers that do. In this case pound will sit in front of a cluster of mongrel servers. This arrangement is similar to that illustrated on the Using Lighttpd with Mongrel page, except pound replaces lighttpd.
Requirements
We assume that the following:
- Pound and the mongrel cluster are running on the same machine[1].
- Pound 2.0.4 is built and installed, including SSL support if desired.
- The mongrel gem is installed.
- The mongrel_cluster gem is installed.
These instructions were performed on CentOS 4.3 using Ruby 1.8.4 from the CentOS 4 test repository. They should apply on other Linux distributions. They may work for other OSes, but please see the pound website for additional information.
Mongrel Cluster Setup
First we need to prepare our rails application to run in a mongrel cluster. In this example we will use mongrel_cluster to run three mongrel instances on ports 8000, 8001, and 8002. We then launch the mongrel cluster:
$ cd railsapp/ $ mongrel_rails cluster::configure -p 8000 -N 3 $ mongrel_rails cluster::start
We should now have three instances of our rails app running on ports 8000, 8001, and 8002.
Configuring Pound
Now we configure pound to proxy requests to the rails cluster we just created. We will configure pound to accept both HTTP and HTTPS traffic on ports 80 and 443 respectively. Pound will then proxy requests to the Services listed in the configuration file. Our configuration file (/usr/local/etc/pound.cfg) looks like this:
ListenHTTP
Address 0.0.0.0
Port 80
Service
BackEnd
Address 127.0.0.1
Port 8000
End
BackEnd
Address 127.0.0.1
Port 8001
End
BackEnd
Address 127.0.0.1
Port 8002
End
End
End
ListenHTTPS
Address 0.0.0.0
Port 443
Cert "/usr/local/etc/test.pem"
# pass along https hint
AddHeader "X-Forwarded-Proto: https"
HeadRemove "X-Forwarded-Proto"
Service
BackEnd
Address 127.0.0.1
Port 8000
End
BackEnd
Address 127.0.0.1
Port 8001
End
BackEnd
Address 127.0.0.1
Port 8002
End
End
End
</code>
</pre>
Before starting pound, we need to make sure our SSL certificate is present. If not we can quickly generate a test certificate:
$ openssl req -x509 -newkey rsa:1024 -keyout test.pem \ -out test.pem -days -nodes
It should now be safe to start pound:
$ sudo pound -f /usr/local/etc/pound.cfg
Our Rails application should now be available at http://127.0.0.1/ and https://127.0.0.1/.
Testing SSL in Rails
The line AddHeader "X-Forwarded-Proto: https" in the ListenHTTPS section tells pound to add a header to the request as it is passed back to the mongrel servers[2]. This will tell the rails application that the request was originally an SSL request. We can test this with the following simple Rails controller, app/controller/test_controller.rb:
class TestController < ApplicationController
def index
@sslyn = request.ssl?
end
end
And the accompanying view, app/views/test/index.rhtml:
<h1>test</h1> SSL: < %= @sslyn %>
Visiting http://127.0.0.1/Test/ should show SSL: false while visiting https://127.0.0.1/Test/ should return SSL: true.
Building Pound on OSX
OSX has specific problems when building pound, but you can follow Trotter Cashion's to get everything working.
fn1. It is not required that pound run on the same machine as the mongrel servers. It was just chosen for this example.
fn2. Thanks to Joshua Harvey's post on the Mongrel mailing list for this fix.
