Thursday, November 22, 2007

Ruby on Rails and Lighttpd(SSL) Installation

Ruby on Rails and Lighttpd(SSL) Installation

The goal of this document is to explain how to set up Ruby on Rails on Lighttpd with SSL enabled and MySQL running in the background. It will cover the proper configuration of the database, as well as how to configure Rails for sending emails. Finally, it will walk through a sample Rails application that uses partials to render a basic website template, with separate header, content, and footer sections.

I found it difficult to find all of this information in one place on the internet, so I hope that this document is helpful for anyone configuring a Rails development environment or building their first Rails application in a Linux environment.

Ruby is an interpreted, dynamically-typed, object-oriented programming language, while Rails is a web development framework that uses the Model-View-Controller software design pattern for building web applications. Rails applications are written in Ruby.

Lighttpd is a fast and lightweight web server. Ruby on Rails provides an excellent abstraction of the backend database, and in our case, we will be using MySQL as the backend database.

I. Check the system

Before installing, let's check that our system has the necessary tools so that the installation process can proceed smoothly. The system we'll be setting up should be similar to my own.
$ echo $SHELL
/bin/bash

$ uname -a
Linux dash.bryanhinton.com 2.6.18-8.1.10.el5 #1 SMP Thu Aug 30 20:43:15 EDT 2007 \
i686 i686 i386 GNU/Linux

$ echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/bin: \
/usr/bin:/home/bryan/bin:/usr/local/bin:/usr/sbin

$ echo $LD_LIBRARY_PATH
/usr/local/lib:/usr/lib:/lib

$ make -v
GNU Make 3.81

$ autoconf -V
autoconf (GNU Autoconf) 2.59

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info \
--enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib \
--enable-__cxa_atexit --disable-libunwind-exceptions \
--enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada \
--enable-java-awt=gtk --disable-dssi --enable-plugin \
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre \
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)

II. Check the host configuration on the network

Change the hostname.

$ su
*******

# hostname
WCLI404892341

# hostname dash.bryanhinton.com

# hostname
dash.bryanhinton.com

Now Open /etc/sysconfig/network and /etc/hosts and make sure that they look like the following:

# cat /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=yes
HOSTNAME=dash.bryanhinton.com

# cat /etc/hosts
127.0.0.1       localhost.localdomain localhost
74.53.242.146   dash.bryanhinton.com    dash
::1             localhost6.localdomain6 localhost6

III. Install Ruby 1.8.6 patchlevel 110, RubyGems 0.9.5, and Ruby FastCGI Bindings

As of November 24, 2007, 1.8.6-p110 is the recommended, stable version and 0.9.5 is the recommended, stable version of RubyGems. RubyGems is the Ruby package management system and a gem is a packaged Ruby application or library. 

# exit
$ mkdir $HOME/src
$ cd $HOME/src
$ wget http://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.gz
$ tar -xzvf ruby-1.8.6.tar
$ cd ruby-1.8.6
$ ./configure
$ make
$ su
*******

# make install

# exit

$ which ruby
/usr/local/bin/ruby

$ ruby -v
ruby 1.8.6 (2007-09-23 patchlevel 110) [i686-linux]

$ cd $HOME/src

$ wget http://rubyforge.org/frs/download.php/28174/rubygems-0.9.5.tgz

$ tar -xzvf rubygems-0.9.5.tgz

$ cd rubygems-0.9.5

$ su
******

# ruby setup.rb

# exit

# gem -v
0.9.5

# gem install fcgi

IV. Install Rails

# gem install rails --include-dependencies

V. Install Lighttpd with SSL

# openssl version
OpenSSL 0.9.8b 04 May 2006

# exit

$ cd $HOME/src

$ wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.gz

$ tar -xzvf  lighttpd-1.4.18.tar.gz

$ cd lighttpd-1.4.18

$ ./configure --with-openssl --with-openssl-libs=/usr/lib/openssl
...
...
...
Plugins:

enabled:
  mod_access
  mod_accesslog
  mod_alias
  mod_auth
  mod_cgi
  mod_compress
  mod_dirlisting
  mod_evhost
  mod_expire
  mod_extforward
  mod_fastcgi
  mod_flv_streaming
  mod_indexfiles
  mod_proxy
  mod_redirect
  mod_rewrite
  mod_rrdtool
  mod_scgi
  mod_secdownload
  mod_setenv
  mod_simple_vhost
  mod_ssi
  mod_staticfile
  mod_status
  mod_trigger_b4_dl
  mod_userdir
  mod_usertrack
  mod_webdav
disabled:
  mod_cml
  mod_magnet
  mod_mysql_vhost

Features:

enabled:
  auth-crypt
  compress-bzip2
  compress-deflate
  compress-gzip
  large-files
  network-ipv6
  network-openssl
  regex-conditionals
disabled:
  auth-ldap
  stat-cache-fam
  storage-gdbm
  storage-memcache
  webdav-locks
  webdav-properties

$ make

$ su
******

# make install

# mkdir /etc/lighttpd/

# cp doc/lighttpd.conf /etc/lighttpd/

# cp doc/rc.lighttpd /etc/init.d/lighttpd

# chmod +x /etc/init.d/lighttpd

# mkdir /var/www

# mkdir /var/www/html

# groupadd lighttpd

# useradd -g lighttpd -d /var/www -s /bin/false lighttpd

# chown -R lighttpd.lighttpd /var/www

# chown -R lighttpd.lighttpd /var/log/lighttpd

Now let's Configure Lighttpd. As stated earlier, there is a public IP address bound to the network card. We are going to bind the lighttpd daemon to the public IP address on port 80 and port 443. This assumes that a correctly configured SSL certificate. The following lines in /etc/init.d/lighttpd.conf should look like the following:

server.username            = "lighttpd"
server.groupname           = "lighttpd"
accesslog.filename          = "/var/log/lighttpd/access.log"
$HTTP["host"] =~ "bryanhinton\.com$" {
  server.document-root = "/var/www/html/bryanhinton/public/"
  accesslog.filename = "/var/www/html/bryanhinton/log/access.log"
  server.indexfiles = ( "dispatch.fcgi", "index.html" )
  server.error-handler-404 = "/dispatch.fcgi"

  # rails stuff
  #### fastcgi module
  fastcgi.server = (
    ".fcgi" => (
      "test" => (
        "socket" => "/tmp/test1.socket",
        "bin-path" => "/var/www/html/bryanhinton/public/dispatch.fcgi",
        "min-procs" => 1,
        "max_procs" => 2
      )
    )
  )
}
$SERVER["socket"] == "74.53.242.146:443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/lighttpd/ssl/bryanhinton.com/bryanhinton.pem"
  server.name = "bryanhinton.com"
  server.document-root = "/var/www/html/bryanhinton/public/"
}

VI. Start Lighttpd

# /etc/init.d/lighttpd start

VII. Configure a Rails Application

First, let's make sure our standard login ID is associated with the lighttpd group. Open /etc/groups and make sure that there is a line that looks like the following:

lighttpd:x:521:lighttpd,LOGIN_ID

Configure a Rails Application

$ cd /var/www/html

$ rails bryanhinton

$ cd bryanhinton

$ ruby script/generate controller Content

$ rm public/index.html

edit config/routes.rb

# add this to line 21
map.connect ':action', :controller => 'Content'


# original line 24
#map.connect '', :controller => "welcome" 

# change to this on line 24
map.connect '', :controller => 'Content'

Setup smtp to send e-mail from Rails. Modify config/environments/development.rb so that it looks like the following:

config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
   :address => "smtphost.bryanhinton.com"
   :port => 25,
   :domain => "bryanhinton.com"
   :authentication => :log
   :user_name => "INSERT USERNAME HERE"
   :password => "INSERT PASSWORD HERE"
}

IIX. Create a development database in MySQL and then Configure in Rails

$ mysqladmin -u myusername create bryanhinton_development -p

$ gem install mysql

Edit config/database.yml and ensure that it looks similar to the following. We are only setting up a development database

development:
  adapter: mysql
  database: bryanhinton_development
  username: MY_MYSQL_USER_NAME
  password: MY_MYSQL_PASSWORD
  socket: /var/lib/mysql/mysql.sock

IX. Test the database connection

$ cd /var/www/html/bryanhinton
$ rake db:migrate

X. Create site layout

$ cd /var/www/html/bryanhinton/app/views/layouts

Place the following lines in application.rhtml

<html>
<body>
<%= render :partial => "layouts/header" %>
<%= render :partial => "layouts/leftnav" %>
<%= render :partial => "layouts/rightnav" %>
<%= yield :layout %>
<%= render :partial => "layouts/footer" %>
</body>
</html>

Create the files that application.rhtml references

$ echo "My Header" > _header.rhtml
$ echo "Left Menu" > _leftnav.rhtml
$ echo "Right Col News" > _rightnav.rhtml
$ echo "My Footer" > _footer.rhtml

XI. Create an index method in the Content controller

Place the following lines in /var/www/html/bryanhinton/app/controllers/content_controller.rb

class ContentController < ApplicationController
def index
end

XII. Create a view for the index method

Create a view for the index method called index.rhtml in /var/www/html/bryanhinton/app/views/content

$ cd /var/www/html/bryanhinton/app/views/content

$ echo "Hello World!" > index.rhtml

XIII. Test the installation!

Open up a web browser and go to the site URL i.e. http://bryanhinton.com OR http://bryanhinton.com/index