It’s always interesting to see how one can replicate the functionality of a known development environment ( the world of Java Web Apps in my case ) inside of a new environment, Rails. One of the exercises I was trying to mimic in Rails was having some traffic go over HTTP and some go over HTTPS.
There is a strong movement to have all traffic go over HTTPS but since it is a bit more costly ( ex: having SSL certs for a CDN so your images don’t pitch “unsecure” errors ) it is still nice to segregate the secure from the non secure parts of your application.
Below is a step-by-step guide to getting this configuration up and running. Pardon some of the brevity but some basic amount of Rails, Passenger and Apache knowledge is required.
Step-by-step guide
Update your Gemfile for your test app with Passenger server
1234
group :development do
# passenger server instead of webbrick
gem "passenger", "~> 4.0.20"
end
Add the VirtualHost entries pointing to your app. This way we can reference things by quasi real url.
Modify your host entires ( /etc/hosts or %SystemRoot%\system32\drivers\etc\hosts ) to include the following
1
127.0.0.1 test-domain.com www.test-domain.com
Create self signed certs for connecting over HTTPS. For this you will need to make sure openssl is installed
This is easy to to in linux and OSX comes with it preinstalled
Linux ( ubuntu )
1
sudo apt-get install openssl
Linux ( redhat / centos )
1
sudo yum install openssl
OSX using homebrew ( a default should be installed )
1
sudo brew install openssl
Create directory for self signed certs
12345
cd /projects
mkdir ssl
cd ssl
mkdir test-domain
cd test-domain
Generate a host key
1
sudo ssh-keygen -f test-domain.key
This should generate the following similar output ( the image will vary based on the passphrase )
12345678910111213141516171819
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in test-domain.key.
Your public key has been saved in test-domain.key.pub.
The key fingerprint is:
a3:cd:70:7a:f5:1d:7b:44:ea:b1:b8:4b:19:ac:0e:5b root@user.local
The key's randomart image is:
+--[ RSA 2048]----+
| |
| |
| .|
| . o |
| . S . o + .|
| B o o * * |
| o = E = = .|
| . = . . . |
| . . o. |
+-----------------+
Create a nopass key version so Apache does not prompt you for a password every time you restart. Or if you want that functionality just use the “test-domain.key” file instead.
Configure Apache
Modify the apache httpd.conf file or create a new *.conf file just for these settings
Add the Passenger load statements to your httpd.conf file
Obviously you will need to modify the paths that match your system
# TEST-DOMAIN CONFIG
NameVirtualHost *:80
NameVirtualHost *:443
# handle Apache connection to Passenger
<VirtualHost *:80>
# define server details
ServerName test-domain.com
ServerAlias www.test-domain.com
# be sure to point to 'public'!
DocumentRoot /projects/test-domain/public
# run in dev mode
RackEnv development
# some passenger config details
PassengerMinInstances 1
PassengerPreStart http://test-domain.com/
PassengerHighPerformance on
<Directory "/projects/test-domain/public">
Options -MultiViews
Allow from all
</Directory>
</VirtualHost>
# Provide an HTTPS entry point as well but one that will not spin up a second rails instance
# but rather redirect traffic accordingly
<VirtualHost _default_:443>
# to run in dev mode
RailsEnv development
# Be sure to point to 'public'!
DocumentRoot /projects/test-domain/public
# define server details
ServerName test-domain
ServerAlias www.test-domain.com
# ssl details
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /projects/ssl/test-domain/test-domain.crt
SSLCertificateKeyFile /projects/ssl/test-domain/test-domain.nopass.key
# rails needs the header for its own processing
RequestHeader set X_FORWARDED_PROTO 'https'
# this is just passing a proxy to a localhost server
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost/
ProxyPassReverse / http://localhost/
</VirtualHost>
You will get errors in your browser about the HTTPS connection being untrusted but that is because you are using a self signed cert. If you were to substitute a proper one this issue would go away.
Now that you have HTTPS running you can do things like integrate Devise into it so all your authentication is handled over a secure connection.
Here is a quick example of setting all Devise functionality to go over HTTPS
Make sure to include the Devise gem in your app
12
# authentication
gem 'devise'
Now install it
1
rails generate devise:install
And finally generate a user model to go with it
1
rails generate devise MODEL
Once you have that done you can force Devise to HTTPS traffic by adding the following to your development.rb or .rb files
1234
# for enforcing SSL on various user areas
config.to_prepare { Devise::SessionsController.force_ssl }
config.to_prepare { Devise::RegistrationsController.force_ssl }
config.to_prepare { Devise::PasswordsController.force_ssl }
Also if you want to force a specific controller to go over SSL you can use the force_ssl method
1234567891011121314
class HomeController < ApplicationController
# this specifies that the test_ssl controller will be the only one using SSL
force_ssl :only => [:test_ssl]
# index will be served over HTTP
def index
end
# test_ssl will be served over HTTPS
def test_ssl
end
end