Sunday, October 4, 2015

Running rails app with Unicorn + Nginx


If you have come from PHP background , you will probably loose your nerve trying to get a simple hello world rails app to work with your server. Getting rails app to work with the server is a little different from any php apps where you just have to place your php app inside the /html folder(in my case).

My system has RVM, rails , ruby, nginx, postgres.

First we need to install unicorn. Unicorn is an application server. Since unicorn cant not be accessed by users directly, we will use Nginx as a reverse proxy.

Navigate to your project directory and open your Gemfile and add gem 'unicorn' gem. Then run bundle install.
Now we need to configure it.

Inside your config directory add unicorn.rb file.

unicorn.rb

# set path to application
app_dir = File.expand_path('./')
shared_dir = "#{app_dir}/tmp"
working_directory app_dir


# Set unicorn options
worker_processes 2
preload_app true
timeout 30

# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64

# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"

# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"


Now lets create the required directories

mkdir -p tmp/log tmp/sockets tmp/pids 

Give those directories necessary read/write permission
Now we will create a init script that will load on boot.

sudo nano /etc/init.d/unicorn_appname
 
You can name appname whatever you want
unicorn_appname

#!/bin/sh

### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the unicorn app server
# Description:       starts unicorn using start-stop-daemon
### END INIT INFO

set -e

USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"

# app settings
USER="sushant"
APP_NAME="appname"
APP_ROOT="/usr/share/nginx/html/app" #in my case
ENV="development"

# environment settings
PATH="/home/$USER/.rvm/shims:/home/$USER/.rvm/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"

# make sure the app exists
cd $APP_ROOT || exit 1

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
  start)
    sig 0 && echo >&2 "Already running" && exit 0
    echo "Starting $APP_NAME"
    su - $USER -c "$CMD"
    ;;
  stop)
    echo "Stopping $APP_NAME"
    sig QUIT && exit 0
    echo >&2 "Not running"
    ;;
  force-stop)
    echo "Force stopping $APP_NAME"
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
  restart|reload|upgrade)
    sig USR2 && echo "reloaded $APP_NAME" && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    $CMD
    ;;
  rotate)
    sig USR1 && echo rotated logs OK && exit 0
    echo >&2 "Couldn't rotate logs" && exit 1
    ;;
  *)
    echo >&2 $USAGE
    exit 1
    ;;
esac


Update the scripts permission and enable unicorn to boot on start

sudo chmod 755 /etc/init.d/unicorn_appname
sudo update-rc.d unicorn_appname defaults
 
Now open

sudo nano /etc/nginx/sites-available/default
 
default

upstream app {
    # Path to Unicorn SOCK file, as defined previously
    server unix:/usr/share/nginx/html/app/tmp/sockets/unicorn.sock fail_timeout=0; #in my case
}

server {
    listen 80;
    server_name example.com;

    root /usr/share/nginx/html/app/public; #in my case

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}
  

Open your hosts file and add
127.0.0.1       example.com
then
sudo service unicorn_appname restart
sudo service nginx restart  If you browse to example.com your app should be running

No comments:

Post a Comment