SSL For Apache And Rails

Introduction

For myriad reasons I’ve decided to start writing my own website and I’m doing that using Ruby On Rails. Unfortunately I hit a snag. I wanted to secure some parts of the site using SSL whilst leaving others open. To do this I needed to, among other things, front the rails server (in my case that’s WEBrick) with Apache and have the later do the proxy pass through magic.

I spent a lot of time in search engines reading various different articles trying to work out how to do this, but not matter which instructions I followed I couldn’t manage to get it to work. I did eventually find a solution though. This article is just to detail that solution so others don’t have to do the same level of research and gnashing of teeth that I did.

Before I forget, these instructions work on my reasonably clean Ubuntu Gutsy install running on my Rizeon (actually a Compal IFL90) laptop. which reminds me… If anyone out there has an IFL90 which they’re having Ubuntu trouble with I recommend Louis-Dominique’s site which gave me a lot of good pointers.

Assumptions

I’m assuming that you’ve installed RoR and Apache2 using your preferred method. These instructions are all about getting them to play nicely together.

SSL Certificate: Self Signing

Because my application is in development mode I just need a certificate to test with, which is where self-signing comes in. See the instructions on this page on how to download and create a self-signed certificate.

Apache2: Enabling the mods

Now, I didn’t download anything extra when I used apt-get to install Apache2, so it’s my belief that it downloaded the list of following mods when Apache was installed. Therefore, I also believe that all you need to do is enable them.

The following incantations will do the enabling, if you get errors because certain mods are missing from your install then I’m afraid that you’re going to have to find out how to install them on your own, sorry.

$ sudo a2enmod ssl
$ sudo a2enmod proxy
$ sudo a2enmod rewrite
$ sudo a2enmod proxy_balancer
$ sudo a2enmod proxy_http
$ sudo a2enmod headers

Apache2: Setting up the VirtualHost

We need to set up some virtual hosts for Apache to represent our proxied site. I also disabled the default proxy application. Here’s the commands needed, instructions follow.
$ cd /etc/apache2
$ sudo a2dissite default
$ sudo cp sites-available/default sites-available/myapp
$ sudo a2ensite myapp

Where “myapp” is obviously the name of the application I’m trying to set Apache up as a proxy for. The “a2dissite” command disables the default web application inside Apache, and the “a2ensite” command enables our one. I copied the sites-available/default file into sites-available/myapp to make sure that the new file describing myapp has the correct permissions etc. We’ll be scrubbing the contents of this new file completely in the next step.

Still in the terminal and still in the /etc/apache2 directory we need to modify our sites-available/myapp file, which we need to do as route, so obviously using your text editor of choice…;
$ sudo vi sites-available/myapp

Below if the contents of my file, feel free to copy it.

<VirtualHost *:80>
  ServerName localhost
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/
</VirtualHost>

<VirtualHost *:443>
  ServerName localhost
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/
  ProxyPreserveHost On
  RequestHeader set X_FORWARDED_PROTO 'https'

  SSLEngine On
  SSLProxyEngine On
  SSLCertificateFile /etc/ssl/certs/selfsigned.pem
  SSLProxyMachineCertificateFile /etc/ssl/certs/selfsigned.pem
</VirtualHost>

Now I’m the first to admit that I don’t 100% understand what the RequestHeaders line is for. It’s my understanding that because Rails doesn’t have a concept of http/https this line overrides some functionality in the link_to code so the correct “http/https” is appended to the URL as required. But as I say, I’m not totally sure that my understanding is accurate in any way.

Apache2: proxy.conf

We need to configure the apache proxy behaviour. To do this we have to modify the file /etc/apache2/mods-available/proxy.conf We need to tell Apache where to accept proxy requests from. Here’s the snip of my proxy.conf file which allows proxy-ing from localhost.
</Proxy *>
  AddDefaultCharset off
  Order deny,allow
  Deny from all
  Allow from localhost
</Proxy>

We now need to bounce Apache2, so issue the following command;

$ sudo /etc/init.d/apache2 force-reload

You shouldn’t get any errors when Apache2 restarts. If you do, either you’ve not followed the above instructions properly or, more likely, I’ve forgotten a critical part of the instructions. If it’s the latter, please let me know of any problems and I’ll rack my brains (and chalk my nose) and get the missing pieces put up.

Rails: Last Stages

Now, as I mentioned earlier, WEBrick doesn’t understand the concept of SSL but Rails/Ruby needs to know to block requests coming in on HTTP when they should be on HTTPS and to do the appropriate redirects. We do this using the ssl_requirement package…

$ cd ~/myapp
$ ruby script/plugin install ssl_requirement

And now we need to modify our controllers to force this usage. In my setup I have an AdminController which all my, er, administrative controllers extend. This means that I just need to apply a layout to my AdminController to get all the admin-stuff looking the same, it also means that I can modify this controller with the SSL stuff and have that ‘cascade’ down to the other more specific admin-y things. here’s my AdminController…

class AdminController < ApplicationController

$nbsp;$nbsp;include SslRequirement

$nbsp;$nbsp;layout 'admin'

$nbsp;$nbsp;# all methods that extend AdminController should use SSL
$nbsp;$nbsp;def ssl_required?
$nbsp;$nbsp;$nbsp;$nbsp;true
$nbsp;$nbsp;end

end

I’ve overridden the ssl_required method because I want all methods of my admin controllers to use SSL. If you want to be a bit more specific on which methods in a controller need SSL I suggest no overriding this but following the example which you’ll find in ~/myapp/vendor/plugins/ssl_requirement/README

Now start WEBrick in the usual way. If you then browse to http://localhost you should get the default non-ssl rails app you were expecting. But if you browse to a URL which should be on SSL you’ll find you get redirected. So in my case; http://localhost/admin redirects me to https://localhost/admin and from then on all URLs and clicks that should be done on HTTPS are where as all non-secure stuff is done on regular HTTP.

Conclusion

I hope that someone finds these instructions helpful. I’m by no means an expert, I got here just by piecing together instructions found on other sites. But if there are any problems let me be the first to say it works on my computer please post a comment if these instructions don’t work and I’ll do my best to help.

References

For the sake of completeness and politeness below is a list of all the pages I used in getting my install working. I’m sure that you’ll find some (or all) of the commands I’ve listed here on these other pages.

Also, apparentlybecause-let-s-face-it-webrick-sucks. I personally haven’t encountered the same problems that the author has, but in case you have the article has some good instructions on how to install an alternative called Mongrel. I might give that a try later.

About these ads

5 Responses to SSL For Apache And Rails

  1. Lanny says:

    Thanks!

    This really helped a lot.

    I ended up having to apply this too: http://seanharper.net/2008/01/22/webfaction-and-ssl_requirement/

    Also, since you are setting up Apache, you can lighten your load by having Apache serve your static content and images instead of Mongrel.

    Cheers

  2. abc says:

    hi i got the error when i run the command
    sudo /etc/init.d/apache2 force-reload

    Error:

    Syntax error on line 57 of /etc/apache2/sites-enabled/myapp:
    deny requires at least two arguments, ‘from’ followed by hostnames or IP-address wildcards
    …fail!

    i followed every step in this article exatly . did i missed anything plz suggest

  3. Tom says:

    Hi abc,

    According to the instructions above the “deny” word only appears in the /etc/apache2/mods-available/proxy.conf file but yours is complaining about the /etc/apache2/sites-enabled/myapp

    I don’t know if your sites-enabled/myapp file is special in anyway, I’m by no means an SSL/Apache expert. I’d check the contents of these files against what it written above and try again.

    Hope this helps.

    Tom

  4. Raza Ali says:

    Hi, Thank a lot it saved my a lot of time.

  5. Sherlyn says:

    Greetings, I’m Sherlyn and I’ve just recently begun
    to get involved with what you’re speaking about. I don’t know where you’re finding your details,
    but good job even so. I ought to devote some more time learning and understanding much more.
    Thanks for the post: I was looking for this info for my mission.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: