Дек 26 2009

Nginx для Ruby on Rails. Установка passenger.

Сразу скажу, что установка диверсионная, то есть не из портов. В порту nginx присутствует опция для установки модуля passenger, но я, честно говоря не смог разобраться с ним. Все собралось, все вроде хорошо, но абсолютно не понятно где находится passenger_root и т.п. Порт самого passengera заточен под Apache, в общем не приемлимо. По крайней мере я не сторонник ставить левый софт, просто потому что не люблю держать софт который не будет использоваться, а потом вернувшись через длительный промежуток времени к этому серверу в случае аварии, я буду вспоминать зачем тут стоит апачь и что вообще тут должно крутится. Поэтому, я пошел по пути, установки софта из gems.

Начнем с установки gems. gems это система управления пакетами для Ruby.
Ставим его из портов:

cd /usr/ports/devel/ruby-gems
make install clean

Этот порт при надобности втянет все что нужно для работы Ruby.
Теперь можно переходить к установке пассенжера, для его установки, как я уже писал воспользуемся установкой через gems:

gem install passenger

После установки passenger нам понадобятся исходные тексты nginx. Скачать его можно с официального сайта http://www.sysoev.ru/ в разделе nginx -> скачтать.
На момент написания статьи стабильная версия nginx-0.7.64, ее и скачаем. Дальнейшие команды предполагается выполнять в директории /home/share/

mkdir /home/share
cd /home/share
fetch http://sysoev.ru/nginx/nginx-0.7.64.tar.gz
tar xvfz nginx-0.7.64.tar.gz

Теперь можно переходить к сборке nginx с поддержкой модуля passenger, для этого служит команда passenger-install-nginx-module, выполняем ее и попадаем в диалог сборки:

passenger-install-nginx-module

Первое диалоговое окно:

Welcome to the Phusion Passenger Nginx module installer, v2.2.8.
 
This installer will guide you through the entire installation process. It
shouldn't take more than 5 minutes in total.
 
Here's what you can expect from the installation process:
 
1. This installer will compile and install Nginx with Passenger support.
2. You'll learn how to configure Passenger in Nginx.
3. You'll learn how to deploy a Ruby on Rails application.
 
Don't worry if anything goes wrong. This installer will advise you on how to
solve any problems.
 
Press Enter to continue, or Ctrl-C to abort.

Нужно нажать Enter для продолжения работы и после этого, произойдет проверка на наличие необходимых компонент и при наличии всех компонент(компилятора gcc, заголовков для разработки ruby, gem, openssl, rake, fastthread), компоненты должны обязательно найтись, часть из них присутствует в базовой системе FreeBSD, остальное установится вместе с gems и после проверки нам предложат выбор:

Automatically download and install Nginx?
 
Nginx doesn't support loadable modules such as some other web servers do,
so in order to install Nginx with Passenger support, it must be recompiled.
 
Do you want this installer to download, compile and install Nginx for you?
 
1. Yes: download, compile and install Nginx for me. (recommended)
The easiest way to get started. A stock Nginx 0.7.64 with Passenger
support, but with no other additional third party modules, will be
installed for you to a directory of your choice.
 
2. No: I want to customize my Nginx installation. (for advanced users)
Choose this if you want to compile Nginx with more third party modules
besides Passenger, or if you need to pass additional options to Nginx's
'configure' script. This installer will  1) ask you for the location of
the Nginx source code,  2) run the 'configure' script according to your
instructions, and  3) run 'make install'.
 
Whichever you choose, if you already have an existing Nginx configuration file,
then it will be preserved.
 
Enter your choice (1 or 2) or press Ctrl-C to abort:

1-й пункт выбора — это установка готового, собраного nginx, а второй пункт — сборка со своими параметрами. Вот второй пункт нам и подойдет. Вводим 2 и жмем Enter.
Следующий вопрос — где находятся исходные тексты nginx, а находятся они там, куда мы распаковали их /home/share/nginx-0.7.64

Where is your Nginx source code located?
 
Please specify the directory:

Вводим путь /home/share/nginx-0.7.64

И жмем Enter — следующий вопрос — какая базовая директория для установки nginx. По умолчанию предлагают /opt/nginx/ Я сталю nginx по тому же пути по которому собирается он из портов /usr/local

Where do you want to install Nginx to?
 
Please specify a prefix directory [/opt/nginx]:

Вводим /usr/local и опять жмем Enter
Теперь у нас интересуются дополнительными опциями configure:

Extra Nginx configure options
 
If you want to pass extra arguments to the Nginx 'configure' script, then
please specify them. If not, then specify nothing and press Enter.
 
If you specify nothing then the 'configure' script will be run as follows:
 
./configure --prefix='/usr/local' --add-module='/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.8/ext/nginx'
 
Extra arguments to pass to configure script:

Я опять таки использую те же, что и при обычной сборке из порта:

--conf-path=/usr/local/etc/nginx/nginx.conf --sbin-path=/usr/local/sbin/nginx --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx-error.log --user=www --group=www --http-client-body-temp-path=/var/tmp/nginx/client_body_temp --http-proxy-temp-path=/var/tmp/nginx/proxy_temp --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp --http-log-path=/var/log/nginx-access.log --with-http_addition_module --with-http_stub_status_module --with-http_sub_module --with-pcre

Опять жмем Enter и nginx c модулем passenger начнет собираться. В конце сборки мы увидим:

Nginx with Passenger support was successfully installed.
 
Please edit your Nginx configuration file,
and set the passenger_root and passenger_ruby configuration options in the
'http' block, like this:
 
http {
...
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.8;
passenger_ruby /usr/local/bin/ruby18;
...
}
 
After you (re)start Nginx, you are ready to deploy any number of Ruby on Rails
applications on Nginx.
 
Press ENTER to continue.

Вот на эти строки надо обратить особенное внимание. Их нужно сразу добавить в файл конфигурации nginx.
Добавим их и жмем Enter.

user  www;
worker_processes  2;
error_log  /var/log/nginx/nginx-error.log;
pid        /var/run/nginx.pid;
events {
use kqueue;
worker_connections  1024;
multi_accept on;
}
http {
include       mime.types;
default_type  application/octet-stream;
large_client_header_buffers 4 4k;
tcp_nopush on;
sendfile on;
output_buffers   32 512k;
sendfile_max_chunk  128k;
postpone_output  1460;
tcp_nodelay      on;
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.8;
passenger_ruby /usr/local/bin/ruby18;
server_names_hash_bucket_size 64;
client_max_body_size 15m;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"

Файл конфигурации nginx пока сохраним и перейдем к установке Ruby-On-Rails. Ставить его будем из портов:

cd /usr/ports/www/rubygem-rails
make install clean

Вначале будет диалог настройки сборки:

┌────────────────────────────────────────────────────────────────────┐
│                 Options for rubygem-rails 2.3.4                    │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │          [ ] FCGI             FastCGI support                  │ │
│ │          [X] MEMCACHE_CLIENT  MemCache-Client support          │ │
├─└────────────────────────────────────────────────────────────────┘─┤
│                       [  OK  ]       Cancel                        │
└────────────────────────────────────────────────────────────────────┘

Установим поддержку memcached — ruby не особо шустрый интерпритатор, и применение кеширования в memcached любят все програмисты работающие с Ruby on Rails.
Далее дело доходит до сборки порта activerecord

┌────────────────────────────────────────────────────────────────────┐
│              Options for rubygem-activerecord 2.3.4                │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │     [X] NATIVE_MYSQL       Use native MySQL bindings           │ │
│ │     [ ] NATIVE_POSTGRESQL  Use native PostgreSQL bindings      │ │
│ │     [X] NATIVE_SQLITE3     Use native SQLite3 bindings         │ │
├─└────────────────────────────────────────────────────────────────┘─┤
│                       [  OK  ]       Cancel                        │
└────────────────────────────────────────────────────────────────────┘

Сборку activerecord я указал с поддержкой MySQL и SQLite, чаще всего требуется именно MySQL, но иногда просят включать поддержку SQLite, в любом случае с какой базой будет работать Ruby on Rails вам может сказать только програмист, который будет в дальнейшем работать на этом сервере.
После того, как установка Ruby on Rails закончится переходим к созданию проекта. Ruby on Rails сгенерирует все нужные для проекта директории и библиотеки, останется создать базы и настроить nginx.
Проект сгенерируем в /home/share/www и назовем его к примеру test для этого создаем директории:

mkdir /home/share/www

переходим туда и генерируем проект:

cd /home/share/www/
rails -d mysql test

Команда rails служит для генерации проекта, а опции командной строки -d mysql — означает что нужно использовать mysql для хранения данных, а test — название проекта и соответственно директории где находятся все файлы проекта.
Далее проект нужно настроить. Внутри директории test есть директория config, а в ней хранятся файлы настроек. Файл database.yml отвечает за настройки доступа к базе. В нашем случае к базе MySQL. В этом файле присутствует 3 секции development, test и production. Создадим базы под эти все секции.

mysql -uroot -p
create database test_development;
create database test_test;
create database test_production;

И создадим пользователя который будет работать с этими базами.

grant all on test_development.* to 'ruby'@'localhost' identified by 'ruby-777';
grant all on test_test.* to 'ruby'@'localhost' identified by 'ruby-777';
grant all on test_production.* to 'ruby'@'localhost' identified by 'ruby-777';

Теперь установим в файле /home/share/www/test/config/database.yml доступ к базам. Во всех трех секциях пользователя и пароль. Находим строки

username: root
password:

и заменяем на

username: ruby
password: ruby-777

Теперь сменим владельца файлов проекта.

cd /home/share/www/
chown -R www:www  /home/share/www/

А теперь можно вернутся к настрокам nginx.
Виртуальный хост под наш проект будет выглядеть так:

server {
listen       89.252.34.107:80;
server_name  ruby.hilik.org.ua;
root /home/share/www/test/public;
passenger_enabled on;
rails_spawn_method smart;
rails_env development;
}

По сравнению с обычным nginx тут добавились настройки модуля passenger.
passenger_enabled on; — опция включает работу модуля passenger для этого виртуального сервера.
rails_spawn_method smart; — метод вызова Riby on Rails движка.
rails_env development; — это определяет в каком ражиме сейчас находится Ruby on Rails — Develpment, test или production. По большому счету от этого зависит какая база будет использоваться.

Теперь надо запустить все наше хозяйство. Я не зря использовал настройки сходные с типовыми для установки из портов. Поэтому стартовый скрипт можно взять от стандартного, собранного из портов nginx:

#!/bin/sh
# $FreeBSD: ports/www/nginx-devel/files/nginx.sh.in,v 1.9 2009/07/15 16:56:09 dougb Exp $
 
# PROVIDE: nginx
# REQUIRE: LOGIN cleanvar
# KEYWORD: shutdown
 
#
# Add the following lines to /etc/rc.conf to enable nginx:
# nginx_enable (bool):          Set to "NO" by default.
#                               Set it to "YES" to enable nginx
# nginx_profiles (str):         Set to "" by default.
#                               Define your profiles here.
# nginxlimits_enable (bool):    Set to "NO" by default.
#                               Set it to yes to run `limits $limits_args`
#                               just before nginx starts.
# nginx_flags (str):            Set to "" by default.
#                               Extra flags passed to start command.
# nginxlimits_args (str):       Default to "-e -U www"
#                               Arguments of pre-start limits run.
 
. /etc/rc.subr
 
name="nginx"
rcvar=`set_rcvar`
 
start_precmd="nginx_precmd"
restart_precmd="nginx_checkconfig"
reload_precmd="nginx_checkconfig"
configtest_cmd="nginx_checkconfig"
gracefulstop_cmd="nginx_gracefulstop"
upgrade_precmd="nginx_checkconfig"
upgrade_cmd="nginx_upgrade"
command="/usr/local/sbin/nginx"
_pidprefix="/var/run/nginx"
pidfile="${_pidprefix}.pid"
required_files=/usr/local/etc/nginx/nginx.conf
 
[ -z "$nginx_enable" ]          && nginx_enable="NO"
[ -z "$nginxlimits_enable" ]    && nginxlimits_enable="NO"
[ -z "$nginxlimits_args" ]      && nginxlimits_args="-e -U www"
 
load_rc_config $name
 
if [ -n "$2" ]; then
profile="$2"
if [ "x${nginx_profiles}" != "x" ]; then
pidfile="${_pidprefix}.${profile}.pid"
eval nginx_configfile="\${nginx_${profile}_configfile:-}"
if [ "x${nginx_configfile}" = "x" ]; then
echo "You must define a configuration file (nginx_${profile}_configfile)"
exit 1
fi
required_files="${nginx_configfile}"
eval nginx_enable="\${nginx_${profile}_enable:-${nginx_enable}}"
eval nginx_flags="\${nginx_${profile}_flags:-${nginx_flags}}"
eval nginxlimits_enable="\${nginxlimits_${profile}_enable:-${nginxlimits_enable}}"
eval nginxlimits_args="\${nginxlimits_${profile}_args:-${nginxlimits_args}}"
nginx_flags="-c ${nginx_configfile} -g \"pid ${pidfile};\" ${nginx_flags}"
else
echo "$0: extra argument ignored"
fi
else
if [ "x${nginx_profiles}" != "x" -a "x$1" != "x" ]; then
for profile in ${nginx_profiles}; do
echo "===> nginx profile: ${profile}"
/usr/local/etc/rc.d/nginx $1 ${profile}
retcode="$?"
if [ "0${retcode}" -ne 0 ]; then
failed="${profile} (${retcode}) ${failed:-}"
else
success="${profile} ${success:-}"
fi
done
exit 0
fi
fi
 
nginx_checkconfig()
{
echo "Performing sanity check on nginx configuration:"
eval ${command} ${nginx_flags} -t
}
 
nginx_gracefulstop()
{
echo "Performing a graceful stop:"
sig_stop="QUIT"
run_rc_command ${rc_prefix}stop $rc_extra_args || return 1
}
 
nginx_upgrade()
{
echo "Upgrading nginx binary:"
 
reload_precmd=""
sig_reload="USR2"
run_rc_command ${rc_prefix}reload $rc_extra_args || return 1
 
sleep 1
 
echo "Stopping old binary:"
 
sig_reload="QUIT"
pidfile="$pidfile.oldbin"
run_rc_command ${rc_prefix}reload $rc_extra_args || return 1
}
 
nginx_precmd() 
{
nginx_checkconfig
 
if checkyesno nginxlimits_enable
then
eval `/usr/bin/limits ${nginxlimits_args}` 2>/dev/null
else
return 0
fi
}
 
extra_commands="reload configtest upgrade gracefulstop"
run_rc_command "$1"

Размещаем этот стартовый скрипт в /usr/local/etc/rc.d/nginx, далее разрешаем запуск nginx в /etc/rc.conf

echo 'nginx_enable="YES"' >> /etc/rc.conf

и запустим nginx:

/usr/local/etc/rc.d/nginx start

Теперь осталось убедиться, что все работает.
Для этого подключаемся браузером, должна открыться страничка:
ruby1

При нажатии на ссылку «About your application’s environmen» должна открыться вот такая картинка:
ruby4

Если появилась желтенькая картинка, значит тпштч + passenger + Ruby on Rails построен и работает.
В конце приведу свой файл настроек nginx для работы с passenger:

user  www;
worker_processes  2;
error_log  /var/log/nginx/nginx-error.log;
pid        /var/run/nginx.pid;
#google_perftools_profiles /tmp/profile;
events {
use kqueue;
worker_connections  1024;
multi_accept on;
}
http {
include       mime.types;
default_type  application/octet-stream;
large_client_header_buffers 4 4k;
tcp_nopush on;
sendfile on;
output_buffers   32 512k;
sendfile_max_chunk  128k;
postpone_output  1460;
tcp_nodelay      on;
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.8;
passenger_ruby /usr/local/bin/ruby18;
server {
listen       89.252.34.107:80;
server_name  ruby.hilik.org.ua;
root /home/share/www/test/public;
passenger_enabled on;
rails_spawn_method smart;
rails_env development;
}
}

На этом настройка закончена.


Украинская Баннерная Сеть