Bad Gateway with NGinx & Unicorn

I am using NGinx as proxy to load balance the traffic. Behind Nginx their are some unicorn servers. On Friday I did some changes on the server and I realized that I am always running into a Bad Gateway error. The way from Nginx to unicorn worked. But the way back not really.

I googled for it and I found out that the problem is the buffer size on NGinx. After setting the buffer sizes up like this here, it worked fine for me.

proxy_buffer_size   128k;
proxy_buffers   4 256k;
proxy_busy_buffers_size   256k;

You have to add this to your default.conf file in “/etc/nginx/conf”.

Running Unicorn as a Service on Debian Linux

Unicorn is a very fast app server for Ruby on Rails. You just have to go to the APP_ROOT and type in “unicorn_rails”. And your app is running.

The problem with that is, if your server reboots your app is down. And you have to start it again by hand. That is not so cool!

Wouldn’t it be cool if you could start your Ruby on Rails like that:

/etc/init.d/unicorn start

and stop it like that:

/etc/init.d/unicorn stop

like all other services on Linux? And after a reboot unicorn starts automatically.

That is possible. Just use this script here for starting and stopping unicorn.

#!/bin/bash

### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
BUNDLE=/usr/local/bin/bundle
UNICORN=/usr/local/bin/unicorn_rails
KILL=/bin/kill
APP_ROOT=/var/www/my_app/current
PID=$APP_ROOT/pids/unicorn.pid
OLD_PID=$APP_ROOT/pids/unicorn.pid.oldbin
CONF=$APP_ROOT/unicorn.conf.rb
GEM_HOME=/var/www/my_app/shared/bundle/ruby/2.1.0/gems/

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

case "$1" in
  start)
    echo "Starting unicorn rails app ..."
    cd $APP_ROOT
    if [ $USER == "ubuntu" ]
    then
      $BUNDLE exec unicorn_rails -D -c $CONF
    else
      su ubuntu -c "$BUNDLE exec unicorn_rails -D -c $CONF"
    fi
    echo "Unicorn rails app started!"
    ;;
  stop)
    echo "Stoping unicorn rails app ..."
    sig QUIT && exit 0
    echo "Not running"
    ;;
  restart)
    if [ -f $PID ];
    then
      echo "Unicorn PID $PID exists"
      /bin/kill -s USR2 `/bin/cat $PID`
      sleep 30
      echo "Old PID $OLD_PID"
      /bin/kill -9 `/bin/cat $OLD_PID`
    else
      echo "Unicorn rails app is not running. Lets start it up!"
      $0 start
    fi
    ;;
  status)
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    ;;
esac

Just customize the paths to your server and place the script in “/etc/init.d”. And ensure that the script is executable.

chmod ugo+x <YOUR_SCRIPT>

Than navigate to the direcotry “/etc/init.d” and execute this here:

update-rc.d <YOUR_SCRIPT> defaults

That will add your script to the default runlevels. So that your script will be executed by every reboot.

Installing Ruby 1.9.X on Debian Linux

It is pretty easy to install Ruby on Debian. Just execute this as root:

apt-get install ruby1.9.1

That’s it! Depending on that GEMs you want to install you should install this here, too.

apt-get install make bcrypt libxml-ruby1.9.1 libxml2-dev libxslt-dev libpq-dev g++

Your GEMs are at “/var/lib/gem/1.9.1/”. You should add this here your path:

/var/lib/gem/1.9.1/bin

That’s it.

Access PostgreSQL from outside

After you installed PostgreSQL on a debian server, by default it is not accessible from outside. From other servers! It is just accessible from localhost. To change that you need to make it listen to a special ip address and port. On Debian 6 you have to switch to this directory:

/etc/postgresql/8.4/main

Here are the config files for PostgreSQL. You have to edit the “postgresql.conf” file. There is one line called “listen_addresses”. This line you have to enhance:

listen_addresses = 'localhost, <YOUR_SERVER_IP>' # what IP address(es) to listen on;
 # comma-separated list of addresses;
 # defaults to 'localhost', '*' = all
 # (change requires restart)

And with this lines you are controlling the port and the connections.

port = 5432 # (change requires restart)
max_connections = 100 # (change requires restart)

Now you have to restart the postgres service:

/etc/init.d/postgresql restart

That alone is not enough. Now PostgresSQL is listen but you can anyway not access it 🙂

For security reasons you have to edit the “pg_hba.conf” file, too. Here you say which IP address is trustful enough to access the service. Here you have to add a line like this:

host    all         all         192.168.0.19/24        md5

That means that all ip from your network can access all databases and all users.

Setting password for PostgreSQL

After a standard installation of PostgreSQL on Debian linux, there is no password set for the default user postgres. You can set the password by login in as postgres user. If you are root, just type in that:

su postgres

Than you can start the postgres client:

psql

And now execute this command here to set up a password for user postgres.

ALTER USER Postgres WITH PASSWORD '<password>';

That’s it.

screen

How can somebody be so stupid to choose “screen” as product name?

I mean the word “screen” has already a meaning! A very strong meaning! That means it is very difficult to google for the product “screen”. So you have to add more keywords into your search. It is a nightmare!