Securing a Rails app on Passenger with SSL

Posted by Brian in Howto, Rails, tips, web (July 24th, 2012)

Configuring a site for SSL is simple once you understand the process. Unfortunately I don’t set these up all that often so I forget. In my book Web Development Recipes I cover how to set up the certificates on the Apache server, but I don’t explicitly show how to make it work with a Rails application. So here’s how I usually set things up.

Assume we have a Linux-based server running Ubuntu (either 10.04 or 12.04), we keep our sites in /var/www and we will define our virtual host in the file /etc/apache2/sites-available/mysite

We want to make sure all HTTP requests go to HTTPS. To do that, we need to set up security for the site *and* add a redirect, either at the application level or at the server level. Many folks will recommend using Rack:SSL, but I’m just going to let Apache take care of it for me.

To make all this work we’ll need to enable two Apache modules; ssl and rewrite. The rewrite mod may already be enabled so you should scan your /etc/apache2.conf or your other configs for it.

To enable the mods, we use the a2enmod command:

$ sudo a2enmod ssl
$ sudo a2enmod rewrite

Next we need to modify the site definition in /etc/apache2/sites-available/mysite so it uses SSL and our certificates. First we’ll change the host for HTTP on port 80 so it redirects traffic to the secure site, like this:

<VirtualHost *:80>
  ServerName myapp.example.com
  RewriteEngine On
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=permanent]
</VirtualHost>

I’m using named virtual hosts here, so this rewrite only applies to myapp.example.com and none of the other sites I may have set up.

In the same file, we add the definition for the secure site on port 443, the default SSH port. This contains all the info that Passgener needs to spawn the site.

<VirtualHost *:443>
  ServerName myapp.example.com
  DocumentRoot /var/www/myapp/current/public
  <Directory /var/www/myapp/current/public>
    AllowOverride all
    Options -MultiViews
  </Directory>
 
  SSLEngine on 
  SSLOptions +StrictRequire 
  SSLCertificateFile /etc/apache2/certs/myapp.example.com.crt 
  SSLCertificateKeyFile /etc/apache2/certs/myapp.example.com.key 
</VirtualHost>

To make this work, we have to generate the certificate and the key.

We do that by creating the /etc/apache2/certs folder and changing into it:

$ sudo mkdir /etc/apache2/certs
$ cd /etc/apache2/certs

Then we generate our Certificate request which also generates a key.

$ sudo openssl req -new -newkey rsa:2048 -nodes -keyout myapp.example.com.key -out myapp.example.com.csr 

Then we take the csr file and get it signed by the cert admin. Or if we need things secured temporarily, we could
sign it ourselves, knowing that our users will get a nasty warning about unknown certs.

$ openssl x509 -req  -in myapp.example.com.csr \
 -signkey myapp.example.com.key -out myapp.example.com.crt

You really don’t want to go to production with a self-signed certificate though.

Once these files are in the certs directory, we can restart the web server and everything should work as expected.

Comments are closed.

Sorry, the comment form is closed at this time.