The following describes setting up "Ruby On Rails" utilizing lighttpd on a debian server. This should be useful to *nix users who wish to run rails on lighttpd.
lighttpd offers much higher static performance than apache, as well as comparable performance on dynamic pages. The largest benefit is the ability to run your applications on a server other than the webserver, by having your fastcgi processes listen on tcp and telling lighttpd to load balance among many listening fastcgi processes (on as many servers as you like). This not only allows for a much stricter security model (your application need not run on the webserver or as the webserver user), it gives you the ability to scale to many backend application processes while still maintaining only one externally facing webserver.
This document attempts to be detailed enough to start 'from scratch'; however, current rails users will probably find it more useful than first-time Railers. The author recommends checking in to #rubyonrails on the Freenode irc nettwork before diving in, for a first-time rails user/evaluator.
Conventions of this document are as follows:
All commands to be run as root are in Cyan and are prepended with # All commands to be run as a regular user are in Yellow and are prepended with ~$ All newly created configuration files are in Bold and are delimited with --- File <filename> starts and end with --- File <filename> EOF Do not include these delimiters in the configuration file Configuration instructions for lighttpd.conf are in <<<Bold Red>>> And are followed by an example directive that you may or not need to modify
1: Install ruby and gems (Easy Way)
# echo 'deb ftp://bougyman.com unstable main' >> /etc/apt/sources.list
# apt-get update && apt-get install ruby1.8-base libpgsql-ruby1.8 (or libmysql-ruby1.8)
1: The Hard Way
# apt-get install libtest-unit-ruby1.8 libtest-unit-ruby libyaml-ruby1.8 \
libyaml-ruby libpgsql-ruby1.8 libpgsql-ruby ruby1.8 ruby ri1.8 ri \
irb1.8 irb postgresql ruby1.8-dev libcfgi-ruby1.8 libfcgi0
1a: These packages are necessary prerequisites to ruby on rails with the postgresql database server. For mysql support:
# apt-get install libmysql-ruby1.8 libmysql-ruby mysql-server-4.1
1b: Link ruby to /usr/local/bin, for compatibility with rails' defaults
# ln -s /usr/bin/ruby1.8 /usr/local/bin/ruby
2: You should now have either postgresql or mysql server started, time to get gems:
# cd /usr/local/src
# wget http://rubyforge.org/frs/download.php/2412/rubygems-0.8.4.tgz
2a: Extract it:
# tar zxvf rubygems-0.8.4.tgz
-- Weee, watch the scroll
2b: Now install it:
# cd rubygems-0.8.4
# ruby setup.rb config
# ruby setup.rb setup
# ruby setup.rb install
-- More scroll, check for errors, report them to bougy.man@gmail.com
3: Update gem list and get your rails installed
# gem install rails
-- Information about updates, you will be prompted to install rails
-- dependencies here, answer Y to the dependency questions
3a: Create a rails skeleton application for your user (DO THIS AS YOUR USER, NOT ROOT)
Replace 'bougyhome' with any name you choose, noting that from this point on, $RAILS_ROOT
will refer to /home/<username>/path/to/bougyhome, where 'bougyhome' is replaced with your app name
# su - <username>
~$ rails bougyhome
-- Lots of scroll, if this errors out, stop and seek help
3b: Modify your $RAILS_ROOT/public/dispatch.fcgi (add RAILS_ENV line), change this
later to move to 'production'
~$ $EDITOR $RAILS_ROOT/public/dispatch.fcgi
--- File $RAILS_ROOT/public/dispatch.fcgi starts
#!/usr/local/bin/ruby
ENV['RAILS_ENV']="development"
require File.dirname(__FILE__) + "/../config/environment"
require 'dispatcher'
require 'fcgi'
FCGI.each_cgi { |cgi| Dispatcher.dispatch(cgi) }
--- File $RAILS_ROOT/public/dispatch.fcgi EOF
3c: Setup your environments, this example uses postgres, it's expected you are familiar
with creating the necessary databases (createdb/psql/pgadmin3). Modify as needed for
mysql or sqlite
~$ $EDITOR $RAILS_ROOT/config/database.yaml
--- File $RAILS_ROOT/config/database.yaml starts
development:
adapter: postgresql
database: bougyman.com
host: localhost
username: bougyman
password: uh-uh
production:
adapter: postgresql
database: dev-bougyman.com
host: localhost
username: bougyman
password: uh-uh
test:
adapter: postgresql
database: test-bougyman.com
host: localhost
username: bougyman
password: uh-uh
--- File $RAILS_ROOT/config/database.yaml EOF
3d: Go back to root
~$ exit
-- should take you back to root (#)
4: Get lighttpd
# cd /usr/local/src
# wget http://www.lighttpd.net/download/lighttpd-1.3.14.tar.gz
4a: Extract it
# tar zxvf lighttpd-1.3.14.tar.gz
-- A bit of scroll
4a 1/2: You need to install any dependencies you'll need for lighttpd, such as openssl
4b: build a debian package
# cd lighttpd-1.3.7
# dpkg-buildpackage
-- Lots of scroll, should end with:
dpkg-deb: building package `lighttpd' in `../lighttpd_1.3.14-1_i386.deb'.
dpkg-genchanges
dpkg-genchanges: including full source code in upload
dpkg-buildpackage: full upload; Debian-native package (full source is included)
4c: install lighttpd debian package
# cd /usr/local/src
# dpkg -i lighttpd_1.3.14-1_i386.deb
5: Set up services (this will install a supervisor to use)
# apt-get install runit
5a: Create the service directories
# mkdir /home/<username>/service
# chown <username> /home/<username>/service
# mkdir -p /etc/runit/homeservices/<username>/log/main
# chown -R <username> /etc/runit/homeservices/<username>/log
5b: create the runscript to start your users services, using your favorite editor (i.e. vi /etc/runit/homeservices/<username>/run)
# $EDITOR /etc/runit/homeservices/<username>/run
--- File /etc/runit/homeservices/<username>/run Starts
#!/bin/sh
exec chpst -u <username> runsvdir /home/<username>/service
--- /etc/runit/homeservices/<username>/run EOF
5c: Then create a log starter file as /etc/runit/homeservices/<username>log/run
# $EDITOR /etc/runit/homeservices/<username>log/run
--- File start: /etc/runit/homeservices/<username>/log/run
#!/bin/sh
exec chpst -u <username> svlogd -t ./main
--- /etc/runit/homeservices/<username>/log/run EOF
5d: Make them executable
# chmod 700 /etc/runit/homeservices/<username>/run
# chmod 700 /etc/runit/homeservices/<username>/log/run
5e: start the service
# ln -s /etc/runit/homeservices/<username> /var/service
-- wait 5 seconds, then
# runsvstat -l /var/service/<username>
-- Should output status, similar to (but more like 2 seconds)
/var/service/bougyman:
run (pid 28349) 1265329 seconds
log: run (pid 28348) 1265330 seconds
5f: Leave root at this time and log in as the <username> chosen above
~ is your users home directory from here on out.
# su - <username>
or
# exit
login: username
password: *******
~$ export RAILS_ROOT=~/bougyhome
-- replace ~/bougyhome with whatever you named your application
6: setup your local services directory
~$ mkdir -p ~/services/lighttpd/log
~$ cd services/lighttpd/log
~$ ln -s $RAILS_ROOT/log ./main
~$ cd ~/services/lighttpd
6a: Create the service file for lighttpd (~/services/lighttpd/run)
~$ $EDITOR ~/services/lighttpd/run
--- File ~/services/lighttpd/run starts
#!/bin/sh -e
exec 2>&1\
/usr/sbin/lighttpd -D -f ~/services/lighttpd/lighttpd.conf
--- ~/services/lighttpd/run EOF
6b: Create the service logging file for lighttpd (~/services/lighttpd/run)
--- File ~/services/lighttpd/run starts
#!/bin/sh -e
exec svlogd -t ./main
--- ~/services/lighttpd/run EOF
6c: Create your lighttpd.conf (authors instructions in <<<Stuff>>>)
~$ cp /etc/lighttpd/lighttpd.conf ~/services/lighttpd/
~$ $EDITOR ~/services/lighttpd/lighttpd.conf
--- File ~/services/lighttpd/lighttpd.conf starts
# lighttpd configuration file
#
# use a it as base for lighttpd 1.0.0 and above
#
# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $
############ Options you really have to take care of ####################
## modules to load
# at least mod_access and mod_accesslog should be loaded
# all other module should only be loaded if really neccesary
# - saves some time
# - saves memory
server.modules = (
#<<<mod_rewrite needs to be enabled>>>
"mod_rewrite",
# "mod_redirect",
"mod_access",
# "mod_auth",
# "mod_status",
#<<<mod_fastcgi needs to be enabled>>>
"mod_fastcgi",
# "mod_simple_vhost",
# "mod_evhost",
# "mod_cgi",
# "mod_compress",
# "mod_ssi",
# "mod_usertrack",
# "mod_rrdtool",
"mod_accesslog" )
## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
#<<<Set to full path to your $RAILS_ROOT/public>>>
server.document-root = "/home/bougyman/www/bougyhome/public"
## where to send error-messages to
#<<<Set to full path to your $RAILS_ROOT/log/lighttpd.error.log>>>
server.errorlog = "/home/bougyman/www/bougyhome/log/lighttpd.error.log"
# files to check for if .../ is requested
server.indexfiles = ( "index.php", "index.html",
"index.htm", "default.htm" )
--- SNIP ---
#### accesslog module
#<<<Full path to $RAILS_ROOT/log/access.log>>>
accesslog.filename = "/home/bougyman/www/bougyhome/log/access.log"
## deny access the file-extensions
#
# ~ is for backupfiles from vi, emacs, joe, ...
# .inc is often used for code includes which should in general not be part
# of the document-root
url.access-deny = ( "~", ".inc" )
######### Options that are good to be but not neccesary to be changed #######
## bind to port (default: 80)
#<<<Must set this to a high port (>1024) so your regular user can open the socket
server.port = 8888
## bind to localhost (default: all interfaces)
#<<<Set to 127.0.0.1 for now, uncomment to listen on all interfaces later>>>
server.bind = "127.0.0.1"
--- SNIP ---
#<<<Comment out all of these, they only apply to root>>>
### only root can use these options
#
# chroot() to directory (default: no chroot() )
#server.chroot = "/"
## change uid to <uid> (default: don't care)
#server.username = "wwwuser"
## change uid to <uid> (default: don't care)
#server.groupname = "wwwgroup"
#### compress module
#compress.cache-dir = "/var/tmp/lighttpd/cache/compress/"
#compress.filetype = ("text/plain", "text/html")
#### fastcgi module
## read fastcgi.txt for more info
#<<<Here is the dirty work, feel free to eliminate the .php entry if you don't need it>>>
#<<<for the php4 entry to work you need to 'apt-get install php4-cgi'>>>
#<<<bin-path should be the full path to $RAILS_ROOT/public/dispatch.fcgi>>>
#<<<you can spawn multiple fastcgi processes, 5 is a good starting point>>>
fastcgi.server = (
".fcgi" =>
( "localhost" =>
(
"socket" => "/tmp/rails.socket",
"bin-path" => "/home/bougyman/www/bougyhome/public/dispatch.fcgi"
)
),
( "localhost" =>
(
"socket" => "/tmp/rails1.socket",
"bin-path" => "/home/bougyman/www/bougyhome/public/dispatch.fcgi"
)
),
( "localhost" =>
(
"socket" => "/tmp/rails2.socket",
"bin-path" => "/home/bougyman/www/bougyhome/public/dispatch.fcgi"
)
),
( "localhost" =>
(
"socket" => "/tmp/rails3.socket",
"bin-path" => "/home/bougyman/www/bougyhome/public/dispatch.fcgi"
)
),
( "localhost" =>
(
"socket" => "/tmp/rails4.socket",
"bin-path" => "/home/bougyman/www/bougyhome/public/dispatch.fcgi"
)
),
".php" =>
( "localhost" =>
(
"socket" => "/tmp/php-fcgi.socket",
"bin-path" => "/usr/bin/php4-cgi"
)
)
)
--- SNIP ---
#### url handling modules (rewrite, redirect, access)
# url.rewrite = ( "^/$" => "/server-status" )
# url.redirect = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
#<<<Url rewriting for pretty urls>>>
#<<<You'll need to set the first one to your default controller and action, replacing>>>
#<<<controller=home&action=index2 with your chosen controller and action>>>
url.rewrite = (
"^/$" => "/dispatch.fcgi?controller=home&action=index2",
"^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9%]+)\??([\-_a-zA-Z0-9=&%]*)$" =>
"/dispatch.fcgi?controller=$1&action=$2&id=$3&$4",
"^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$" =>
"/dispatch.fcgi?controller=$1&action=$2&$3",
"^/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$" =>
"/dispatch.fcgi?controller=$1&action=index&$2"
)
--- SNIP ---
--- ~/services/lighttpd/lighttpd.conf EOF
6d: Make your lighttpd server startup files executable
~$ chmod 700 ~/services/lighttpd/run ~/services/lighttpd/log/run
6e: test it out
~$ cd ~/services/lighttpd
~$ ./run
-- should show the server startup, stop here on errors and seek help, else ctrl-c and move to next step
6f: Start the service permanently (supervised)
~$ ln -s ~/services/lighttpd ~/service
-- wait 5 seconds, then
~$ runsvstat -l ~/service/lighttpd
-- should output
/home/bougyman/service/lighttpd: run (pid 12630) 4037 seconds
log: run (pid 12629) 4038 seconds
7: Start creating your rails application! See www.rubyonrails.com for detailed instructions
Debian will start lighttpd on port 80 with the configuration in /etc/lighttpd/lighttpd.conf
when you install. You probably want to
# /etc/init.d/lighttpd stop then # update-rc.d lighttpd remove
so you can use iptables to redirect port 80 to your users port (8888) in the example above.
example iptables rules:
# iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:8888 # iptables -t nat -I POSTROUTING -p tcp --sport 8888 -j SNAT --to 127.0.0.1:80
You'll replace localhost/127.0.0.1 with the ip lighttpd will bind to in production. For now we are only working with 127.0.0.1.
TJ Vanderpoel bougy.man@gmail.com Last update: Jan 9, 2004