What are the steps you need to take to set up SSL on a Ruby on Rails app that is hosted on Apache2/Ubuntu?


NOTE: I moved this from a previous mistaken "community wiki" post.

The other day I was asked by some of our Rails devs to enable SSL on an application.

There are many sources on Google for configuring SSL with Ubuntu and Apache, and some on Rails, and a few with Ubuntu/Apache/Rails, but I wasn't able to find one that I feel was straightforward and comprehensive.

So after spending a bit of time figuring out the exact combination of steps needed to get SSL working on this popular configuration, I decided to make a ServerFault entry on how to get SSL going in your Rails app on Apache2 / Ubuntu.

Feel free to edit/add/comment based on your experiences!

For this case, we are assuming you are getting a certificate from GoDaddy (not a self-signed cert), but you can get your cert from any certificate authority and the steps should be the same.

I’ll use www.yourdomain.com as the example domain we want to secure.

Set Up Your Cert Directory

There are four crypto-related files for SSL that need a home: 1) the CSR (you send to GoDaddy), 2) the private key (which you keep), 3) the actual cert sent to you by GoDaddy, and 4) the intermediate certificate (GoDaddy will send you).

If you have Ubuntu, you probably have an /etc/apache2 folder. So create a folder in there called ssl.

Create Your Private Key

You need openssl for this, so first do:

sudo apt-get install openssl

Then you actually make your private key, like this:

sudo openssl genrsa -des3 -out www.yourdomain.com.key 1024

It will ask you for a password. You’ll remove this later but for now just type something you will remember. This key you will keep locally (don’t send it to GoDaddy).

Create Your CSR

This is the file you’ll actually send to GoDaddy to get your certificate:

sudo openssl req -new -key www.yourdomain.com.key -out www.yourdomain.com.csr

Get Your Cert and Intermediate Cert

Now you go through Godaddy’s (or your certificate authority’s) process for getting your certificate and their intermediate certificate. You’ll send them your CSR to get these. Drop them in your /etc/apache2/ssl folder.

Remove the Password from Your Private Key

This step is optional, but if you don’t do it Apache won’t start automatically on reboot (it will prompt for a password).

sudo mv www.yourdomain.com.key www.yourdomain.com.passkey

sudo openssl rsa -in www.yourdomain.com.passkey -out www.yourdomain.com.key

Set Appropriate Permissions on Your Key Files

You don’t want random people to snag your keys. At this point if you do an ls -l in the /etc/apache2/ssl folder you should see that the files are owned by root. Now we just need to change the permissions so only root can read them:

sudo chmod 400 /etc/apache2/ssl/*

Prep Apache by Installing Mods

Your Apache install probably doesn’t have mod_ssl or mod_headers installed, so you will need to do:

sudo a2enmod ssl
sudo a2enmod headers

Adjust Site Config File in Apache

Assuming your site is already operational with http, you should have a config file already under /etc/apache2/sites-available (like default). Edit that file so that it looks like:

<VirtualHost *:443>
  ServerName  www.yourdomain.com
  ServerAlias www.yourdomain.com
  DocumentRoot /var/apps/yourapp/public

  SSLEngine On
  SSLCertificateFile    /etc/apache2/ssl/www.yourdomain.com.crt
  SSLCertificateKeyFile /etc/apache2/ssl/www.yourdomain.com.key
  SSLCertificateChainFile /etc/apache2/ssl/gd_bundle.crt

  #For RoR "Mongrel"
  RequestHeader set X-Forwarded-Proto "https"

  #Hack for IE
  SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown

…you of course will need to put in your domain where applicable and also put the name of your key files in there as well.

Restart Apache

These changes don't take effect until you restart apache, so do:

sudo /etc/init.d/apache2 restart

Adjust Your Rails App

Now we need to adjust your rails app so that it supports SSL. Edit your /app/controllers/application_controller.rb and add this at the bottom:

  def ssl_required?

If you wanted to get fancy, you could add in some code there to return false if local_request or RAILS_ENV == ‘test’.

That’s it! Hope this saves someone else some web research!

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.