Setup an AWS Ubuntu 10.10 server instance with Ruby on Rails, mysql, nginx, and Passenger

Here are some instructions for setting up ROR to run on an AWS instance.  This tutorial assumes you already have your AWS instance running and you are ssh’ed into the server.

First, set up Ruby from source.  You can do this with apt-get, but I prefer to grab the version directly from the rails source.

First install the necessary libraries. If you don’t install libz-dev, libncurses5-dev, and libreadline5-dev your Rubygems will throw errors.  If you forget this step, all you will need to do to fix it is install the libraries and re-run your sudo make && make install commands.

sudo apt-get install zlib1g zlib1g-dev libxml2 libxml2-dev libxslt-dev libssl-dev openssl libncurses5-dev libreadline5-dev libncurses5-dev libreadline5-dev

Grab the source from http://www.ruby-lang.org/en/downloads/

wget ftp://ftp.ruby-lang.org//pub/ruby/1.9/ruby-1.9.2-p180.tar.gz
tar xzfv ruby-1.9.2-p180.tar.gz
cd ruby-1.9.2-p180
./configure
sudo make && sudo make install

Then check to see that you’ve got ruby working

gem list

You should see some gems.

Install mysql

sudo apt-get install mysql-server

Install passenger with nginx
You probably need this library

sudo apt-get install libcurl4-openssl-dev

Then install the gem and nginx

gem install passenger
passenger-install-nginx-module

Choose to download and compile (1) then hit enter a bunch of times. We’re installing into /opt/nginx (the default).

Add this script to a file name nginx and place it in /etc/init.d

#! /bin/sh
### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: nginx init.d script for Ubuntu 8.10 and lesser versions.
# Description:       nginx init.d script for Ubuntu 8.10 and lesser versions.
### END INIT INFO
#------------------------------------------------------------------------------
# nginx - this script, which starts and stops the nginx daemon for ubuntu.
#
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server.  This \
#		script will manage the initiation of the \
#		server and it's process state.
#
# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf
# pidfile:     /acronymlabs/server/nginx.pid
# Provides:    nginx
#
# Author:  Jason Giedymin
#          .
#
# Version: 1.0 01-Apr-2009 jason.giedymin AT gmail.com
# Notes: nginx init.d script for Ubuntu 8.10 and lesser versions.
#
#------------------------------------------------------------------------------
#                               MIT X11 License
#------------------------------------------------------------------------------
#
# Copyright (c) 2009 Jason Giedymin, http://AcronymLabs.com
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
#                               Functions
#------------------------------------------------------------------------------
. /lib/lsb/init-functions

#------------------------------------------------------------------------------
#                               Consts
#------------------------------------------------------------------------------
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/opt/nginx/sbin/nginx

PS="nginx"
PIDNAME="nginx"				#Lets you do $PS-Master or $PS-Slave
PIDFILE=$PIDNAME.pid                    #pid file
PIDSPATH=/opt/nginx/logs
DESCRIPTION="Nginx Server..."

RUNAS=root				#user to run as

SCRIPT_OK=0				#ala error codes
SCRIPT_ERROR=1				#ala error codes
TRUE=1					#boolean
FALSE=0					#boolean

lockfile=/var/lock/subsys/nginx
NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"

#------------------------------------------------------------------------------
#                               Simple Tests
#------------------------------------------------------------------------------

#test if nginx is a file and executable
test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
        . /etc/default/nginx
fi

#set exit condition
#set -e

#------------------------------------------------------------------------------
#                               Functions
#------------------------------------------------------------------------------

setFilePerms(){

        if [ -f $PIDSPATH/$PIDFILE ]; then
                chmod -f 400 $PIDSPATH/$PIDFILE
        fi
}

configtest() {
	$DAEMON -t -c $NGINX_CONF_FILE
}

getPSCount() {
	return `pgrep -f $PS | wc -l`
}

isRunning(){
	pidof_daemon
	PID=$?

	if [ $PID -gt 0 ]; then
		return 1
        else
                return 0
        fi
}

status(){
	isRunning
	isAlive=$?

	if [ "${isAlive}" -eq $TRUE ]; then
                echo "$PIDNAME found running with processes:  `pidof $PS`"
        else
                echo "$PIDNAME is NOT running."
        fi

}

removePIDFile(){
	if [ -f $PIDSPATH/PIDFILE ]; then
        	rm -f $PIDSPATH/$PIDFILE
        fi
}

start() {
        log_daemon_msg "Starting $DESCRIPTION"

	isRunning
	isAlive=$?

        if [ "${isAlive}" -eq $TRUE ]; then
                log_end_msg $SCRIPT_ERROR
        else
                start-stop-daemon --start --quiet --chuid $RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON
                setFilePerms
		log_end_msg $SCRIPT_OK
        fi
}

stop() {
	log_daemon_msg "Stopping $DESCRIPTION"

	isRunning
	isAlive=$?
        if [ "${isAlive}" -eq $TRUE ]; then
                start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE

		removePIDFile

                log_end_msg $SCRIPT_OK
        else
                log_end_msg $SCRIPT_ERROR
        fi
}

reload() {
	configtest || return $?

	log_daemon_msg "Reloading (via HUP) $DESCRIPTION"

        isRunning
        if [ $? -eq $TRUE ]; then
		`killall -HUP $PS` #to be safe

                log_end_msg $SCRIPT_OK
        else
                log_end_msg $SCRIPT_ERROR
        fi
}

terminate() {
        log_daemon_msg "Force terminating (via KILL) $DESCRIPTION"

	PIDS=`pidof $PS` || true

	[ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE`

	for i in $PIDS; do
		if [ "$i" = "$PIDS2" ]; then
	        	kill $i
			removePIDFile
		fi
	done

	log_end_msg $SCRIPT_OK

}

pidof_daemon() {
    PIDS=`pidof $PS` || true

    [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE`

    for i in $PIDS; do
        if [ "$i" = "$PIDS2" ]; then
            return 1
        fi
    done
    return 0
}

case "$1" in
  start)
	start
        ;;
  stop)
	stop
        ;;
  restart|force-reload)
	stop
	start
        ;;
  reload)
	$1
	;;
  status)
	status
	;;
  configtest)
        $1
        ;;
  terminate)
	$1
	;;
  *)
	FULLPATH=/etc/init.d/$PIDNAME
	echo "Usage: $FULLPATH {start|stop|restart|force-reload|status|configtest|terminate}"
	exit 1
	;;
esac

exit 0

Give it executable permissions

$ sudo chmod +x /etc/init.d/nginx

Now you can run

$ sudo service nginx start|stop|restart

Now edit the /opt/nginx/conf/nginx.conf file

Edit it and remember the paths of your passenger_root and passenger_ruby from it’s current state. Then make the file look like this, but replacing those paths with their current state.

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.7;
    passenger_ruby /usr/local/bin/ruby;
    passenger_max_pool_size 15;

    include       mime.types;
    default_type  application/octet-stream;

    access_log  /var/log/nginx_access.log;
    error_log /var/log/nginx_error.log;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";
    gzip_proxied any;
    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    client_max_body_size       100M;
    client_body_buffer_size    128K;

    proxy_redirect              off;
    proxy_set_header            Host $host;
    proxy_set_header            X-Real-IP $remote_addr;
    proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout       90;
    proxy_send_timeout          90;
    proxy_read_timeout          90;
    proxy_buffer_size           4k;
    proxy_buffers               4 32k;
    proxy_busy_buffers_size     64k;
    proxy_temp_file_write_size  64k;

    include sites-enabled/*;
}

Create directories for nginx configurations

sudo mkdir /opt/nginx/conf/sites-enabled/
sudo mkdir /opt/nginx/conf/sites-available/

create a default site with the following config by running

sudo nano /opt/nginx/conf/sites-available/default
server {
        listen       80;
        server_name  localhost;

        location / {
            root   /var/www/default;
            index  index.html index.htm;
        }

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

Then symlink it in sites-enabled and restart nginx

$ sudo ln /opt/nginx/conf/sites-available/default /opt/nginx/conf/sites-enabled/default

Now when you add a new site, do the same thing, but make the config look more like this.

 server {
         server_name www.blenderbox.com;
         rewrite ^/(.*) http://blenderbox.com/$1 permanent;
}

server {
        rails_env stage;
        listen 80;
        server_name blenderbox.com;
        root /var/www/blenderbox.com/current/public;
        passenger_enabled on;
        passenger_use_global_queue on;
}

Finally, add nginx to update-rc so it starts on reboot.

sudo /usr/sbin/update-rc.d -f nginx defaults

Comments are closed.