Ruby on Rails + SSL + ISPConfig + Apache 2.0 + Mongrel
June 13th, 2007If you are using ISPConfig to manage the virtual hosts on your web server, you will notice that there is no way to separate SSL vs non-SSL Apache directives using the standard web interface. This is a problem if you are writing Ruby on Rails applications and proxying requests through Apache to a Mongrel cluster because Mongrel won’t know what type of requests it is receiving. Being behind the proxy, Mongrel doesn’t know if the original requests are coming via HTTP or HTTPS. The solution is to add RequestHeader set X_FORWARDED_PROTO ‘https’ as a line in your Apache virtual host configuration for the SSL virtual host. I will tell you how to get ISPConfig to handle that for you. I will also show how to get GoDaddy.com ssl certificates working and how our Apache 2.0 randomized proxy balancer works.
We are running Apache 2.0 and proxying to a Mongrel cluster for our latest e-commerce website QuietHeadphones.com which is scheduled to be launched at the end of June. Being an e-commerce site we needed to put the checkout functionality behind SSL. Since Apache is handling both the HTTPS/SSLfunctionality as well as the standard HTTP requests and proxying everything to the Mongrel cluster, the Mongrel cluster doesn’t know which requests are HTTPS and which are HTTP. To tell Rails which requests are HTTPS requests you can set up an environment variable in the Apache virtual host configuration in the httpd.conf file. The environement variable is:
RequestHeader set X_FORWARDED_PROTO ‘https’
In Rails, request.rb checks for that variable and pleasantly handles everything else for you.
Now if you are using ISPConfig to manage the virtual hosts on your web server, you will notice that there is no way to separate SSL vs non-SSL Apache directives using the web interface. Since most of our sites are Ruby on Rails sites and since the RequestHeader variable doesn’t hurt anything if you aren’t using rails, I revised the source code of ISPConfig to always include the RequestHeader set X_FORWARDED_PROTO line in all of the SSL virtual host configurations. That way, anytime you set up a site in ISPConfig and select the SSL option, ISPConfig faithfully inserts the RequestHeader line so that Mongrel knows what sort of requests it is getting.
To make this revision to ISPConfig, open up config.lib.php then edit the SSL-Web section at approximately line 1521 by adding RequestHeader set X_FORWARDED_PROTO ‘https’
file: /root/ispconfig/scripts/lib/config.lib.php
RequestHeader set X_FORWARDED_PROTO ‘https’
Once that is in place, all HTTPS requests will have that request header variable set and regular HTTP requests will not. Then you can use the standard web interface to configure the rest of the Apache directives for your Ruby on Rails application and the Mongrel cluster. Here’s an example of what the Apache Directives text box may look like in ISPConfig.
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyRequests Off
ProxyPassReverse / http://www.mydomain.com:9001/
ProxyPassReverse / http://www.mydomain.com:9002/
ProxyPassReverse / http://www.mydomain.com:9003/
ProxyPreserveHost On
RewriteEngine On
RewriteMap servers rnd:/var/www/webX/rails/map.txt
RewriteRule ^/(images|stylesheets|javascripts)/?(.*) $0 [L]
RewriteRule ^/(.*)$ http://www.mydomain.com:${servers:ports}/$1 [P,L]
Alias /images /var/www/webX/web/images
Alias /stylesheets /var/www/webX/web/stylesheets
Alias /javascripts /var/www/webX/web/javascripts
SSLCertificateChainFile /var/www/webX/ssl/gd_intermediate_bundle.crt
There are a couple things to note in this example. At the time of this writing, we are using Apache 2.0 and, therefore, don’t have access to the mod_proxy_balancer that many people are enjoying with Apache 2.2. Nevertheless, we wanted to run a Mongrel cluster so we are using a randomized proxy balancer by taking advantage of the RewriteMap feature of Apache 2.0. We created a text file that contains the port numbers that each of our Mongrel instances are using separated by pipes as follows:
file: map.txt
ports 9001|9002|9003
Then on each request, Apache randomly selects on of the three ports from the map.txt file and rewrites the request for one of our mongrel instances.
RewriteRule ^/(.*)$ http://www.mydomain.com:${servers:ports}/$1 [P,L]
Lastly, if you buy an SSL certificate from godaddy.com, you will need to add the SSLCertificateChainFile directive to your Apache configuration. Otherwise, most - perhaps all - browsers will complain about the ssl certificate not being trusted. Once you know about that, it’s an easy adjustment to make. Simply give Apache the path to the gd_intermediate_bundle.crt that you will get when you buy your ssl certificate at GoDaddy.com






