Tuesday, July 14, 2009

HOWTO: Configure Apache+Passenger with HTTPS/SSL

The following BASH commands assume you are in a root shell. It is quite convenient to switch using sudo -s; this should allow for plenty cut and paste action.
apt-get update
apt-get install -y ssh #... if like me you are working on a bare-bones VM
At this point I typically close my VM Server console (cause it's pants... until screw up my network and/or ssh config). I connect using keys from Cygwin; much more productive working this way.
apt-get install -y build-essential wget

Install Apache 2

apt-get -y install apache2 apache2-prefork-dev libreadline5-dev
cat > /etc/apache2/httpd.conf <<EOF
ServerName localhost

Install Enterprise Ruby (info) & Passenger

wget http://rubyforge.org/frs/download.php/58677/ruby-enterprise-1.8.6-20090610.tar.gz
tar -xzvf ruby-enterprise-1.8.6-20090610.tar.gz
./ruby-enterprise-1.8.6-20090610/installer <<EOF

/opt/ruby-enterprise-1.8.6-20090610/bin/gem install -y rails # specify version if necessary i.e. -v 2.1.0
cat > /etc/apache2/mods-available/passenger.load <<EOF
LoadModule passenger_module /opt/ruby-enterprise-1.8.6-20090610/lib/ruby/gems/1.8/gems/passenger-2.2.4/ext/apache2/mod_passenger.so

cat > /etc/apache2/mods-available/passenger.conf <<EOF
PassengerRoot /opt/ruby-enterprise-1.8.6-20090610/lib/ruby/gems/1.8/gems/passenger-2.2.4
PassengerRuby /opt/ruby-enterprise-1.8.6-20090610/bin/ruby
/opt/ruby-enterprise-1.8.6-20090610/bin/passenger-install-apache2-module <<EOF


Generate Certificate & Private Key

mkdir -p /etc/apache2/ssl/{crt,key}
openssl req -new -x509 -days 365 -keyout /etc/apache2/ssl/key/server.key -out /etc/apache2/ssl/crt/server.crt -nodes -subj '/O=Working With Mr.B, Ltd/OU=WWW Security Team/CN=workingwithmrb.blogspot.com'

Enable Apache Modules

a2enmod rewrite
a2enmod passenger
a2enmod ssl

Define & Install Virtual Host Rails

cat > /etc/apache2/sites-available/blog <<EOF
<VirtualHost *:80>
    ServerName workingwithmrb.blogspot.com
    DocumentRoot /var/www_rails/blog/current/public
    ErrorLog /var/www_rails/blog/current/log/apache.log

    <Location />
        RewriteEngine on
        RewriteCond %{HTTPS} off
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R]

<VirtualHost *:443>
    ServerName workingwithmrb.blogspot.com
    DocumentRoot /var/www_rails/blog/current/public
    ErrorLog /var/www_rails/blog/current/log/apache-ssl.log

    SSLEngine On
    SSLProtocol -all +TLSv1 +SSLv3
    SSLCertificateFile /etc/apache2/ssl/crt/server.crt
    SSLCertificateKeyFile /etc/apache2/ssl/key/server.key
    SSLVerifyClient optional
    SSLVerifyDepth 1
    SSLOptions +StdEnvVars +StrictRequire
    CustomLog /var/log/apache2/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

a2ensite blog

Distinguish VirtualHosts Listening on Port 80 & 443

sed -i 's,VirtualHost \*,VirtualHost *:80,' /etc/apache2/sites-available/default
sed -i '/NameVirtualHost \*:80/ a NameVirtualHost *:443' /etc/apache2/sites-available/default

Give It A Spin

/etc/init.d/apache2 reload
netstat -napt
The output from netstat should show Apache listening on ports 80 and 443
Remember, if you install all this stuff as root, you must make sure that Apache+Passenger can access the rails application as www-data. Although it's a pretty stupid solution, you can achieve this by simply chmod -R o+rw <rails-app> in the parent directory. A better approach would be to create a user account e.g. called rails that belongs to the www-data group and with a umask of 0002, then anything to do with Rails you should do logged-in as that user.

Hope you find this simple and useful.