Apache Setup for a Non-Root Rails App

Posted by Kelly McCauley on Sep 17, 2007

Introduction

Over the weekend, I wanted to put a small Ruby on Rails application that I had written for myself into production. This small article documents the setup and configuration that I used to get my application running with Apache and a Mongrel cluster back end. The article assumes that the reader knows the basics of Apache administration, Mongrel configuration, and deployment of Ruby on Rails applications.

There are plenty of documentation references for installing a rails application as the root web page. The Agile Web Development with Rails book, in the Setting Up a Deployment Enviroment section, gives a fairly detailed description of the steps needed to deploy an application into production. The Mongrel: Apache documentation is another excellent reference. But I didn’t want to install my rails application at the root of my URL….

My rails application is just a small URL manager called Blink and I wanted it to be served from the private section of my web pages:

https://drotner.org:8443/blink/

I am using Apache as the front end to Blink because I’m using mod_svn to host my Subversion repositories and didn’t want to have yet another front end web server to administer. Blink itself will be running on a cluster of mongrel servers (initially, only one mongrel server).

Setup and Configuration

I first checked out a copy of Blink’s source code, configured Blink, and created the database. The next step was to configure the mongrel cluster. My mongre_cluster init.d script looks for server configurations in /etc/mongrel, so I created /etc/mongrel/blink.drotner.org.8443.mongrel_cluster.yml

1
2
3
4
5
6
7
8
9
10
--- 
prefix: /blink
cwd: /var/www/ssl_drotner_org/apps/blink
log_file: log/mongrel.log
port: "8200"
environment: production
address: 127.0.0.1
servers: 1
user: mongrel
group: mongrel

I set mongrel’s prefix option (line 2) since I want Blink to run under the /blink/ URL path. I started up the mongrel cluster and then used curl to verify that Blink’s mongrel server was running.

root@drotner:/etc/mongrel # curl http://127.0.0.1:8200/blink/
<html><body>You are being <a href="http://127.0.0.1:8200/blink/authn_sessions/new">redirected</a>.</body></html>

curl outputted exactly what I was expecting. The next step was configuring Apache to proxy requests for /blink/ to the back end mongrel cluster.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<VirtualHost 66.241.137.71:8443>
  DocumentRoot "/var/www/ssl_drotner_org/htdocs-secure"
  ServerName drotner.org:8443
  ErrorLog /var/log/apache2/ssl_drotner_org_error_log
  CustomLog /var/log/apache2/ssl_drotner_org_access_log combinedio

  # ... SNIP ...

  ProxyRequests Off
  ProxyVia Full
  RequestHeader set X_FORWARDED_PROTO 'https'

  <Proxy balancer://mongrel_cluster>
    BalancerMember http://127.0.0.1:8200
    #BalancerMember http://127.0.0.1:8201
  </Proxy>

  <Proxy *>
    Order Deny,Allow
    Deny from all
    Allow from all
  </Proxy>

  RewriteEngine On
  # Check for  maintenance file and redirect all requests
  RewriteCond  %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond  %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule  ^/blink/.*$ /system/maintenance.html [L]
  # Rewrite /blink/ to check for static index page
  # RewriteRule ^/blink/$ /index.html [QSA]
  # Rewrite to check for Rails cached page
  RewriteRule ^/blink/([^.]+)$ /blink/$1.html [QSA]
  # Redirect all non-static requests to the mongrel cluster
  RewriteCond %{DOCUMENT_ROOT}/blink/%{REQUEST_FILENAME} !-f
  RewriteRule ^/blink/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

</VirtualHost>

ProxyRequests Off (line 9) is critical and keeps the Apache server from being an open proxy server.

Note that Blink is being served over TLS/SSL. RequestHeader set X_FORWARDED_PROTO 'https' (line 11), in a nutshell, tells rails to write URLs with https:// for location redirects instead of the default http://.

<Proxy balancer://mongrel_cluster>... (lines 13 – 15) tells Apache where to find Blink’s mongrel servers. Each BalanceMember must map to a mongrel server running on the given port.

The rewrite rules, lines 24 – 35, do the grunt work of deciding whether the requests go to the Blink application or elsewhere.

Finally, I restarted my Apache server, and pointed my browser to https://drotner.org:8443/blink/ and got the appropriate index page. Now, back to what I enjoy doing … programming.