Pull to refresh

Ruby on Rails. C локального хоста на VDS за 15 минут

Website development *Ruby on Rails *
Sandbox
Доброго времени суток, хабровчане!

Как переехать на VDS за 15 минут и не углубляться в изучение nginx, unicorn и capistrano. Пошаговая инструкция под катом.

Я постоянно слышу от многих своих знакомых программистов PHP, что они не хотят переходить на рельсы только из-за того, что нет адекватного и дешевого хостинга с нормальной панелью управления. На самом деле вопрос где хостится, если пишешь на рельсах, поднимался уже раз сто на хабре, именно поэтому я об этом и не буду говорить. Когда я первый раз делал проект на рельсах я столкнулся с поиском хостера, но дело даже не в этом, главное было для меня это нетрудоемкий процесс запуска приложения на хостинге. Я решил приобрести себе VDS и использовать его в качестве тестового сервера. Процесс настройки и подготовки VDS был усложнен тем, что я не нашел инструкции от А до Я, а так как я, грубо говоря, не блистал знаниями в настроке не только VDS но и nginx и unicorn и много чего еще. Мне не нужны были конфиги в 200 строк и жутко замороченные настройки для высоконагруженных приложений, моей задачей было просто запустить сайт за минимум денег и времени и отдать его заказчику вместе с этим VDS. В этой статье я хочу написать именно ту инструкцию, которая так была мне нужна, надеюсь, что она будет полезна многим начинающим писать на рельсах и послужит, возможно, дополнительным стимулом для тех PHP программистов, кто все еще сомневается и продолжает юзать фреймворки, которые копируют функционал и фишки Ruby On Rails. Мне кажется это тоже самое, что ставить движок от мерседеса в копейку. Вроде резвенько, но что все равно не то.

Итак, приступим

Что вы должны иметь для начала:
  • Купленный и работающий VDS c любой системой Debian семейства
  • Купленный домен у любого регистратора

Для справки: все действия, в моем случае, выполняются на VDS с Ubuntu Server 11.10.

Установка и настройка nginx

Заходим на машину по ssh через терминал:
:~ ssh root@<ip машины>

Ставим nginx из репозитория:
:~ apt-get install nginx

Создаем директорию для конфигов наших приложений, вдруг их будет несколько:
:~ mkdir /etc/nginx/sites

Пишем конфиг для первого приложения. Я использую vim, но это дело вкуса, можно использовать хоть стандартный nano:
:~ vi /etc/nginx/sites/first_app.conf

Пишем сюда следующее содержимое:
server {
listen 80;
# Имя сервера это то, что будет запускаться.
# Некоторые провайдеры генерируют случайное доменное имя, если это ваш случай, то пишем его сюда.
server_name first_app.com;
root /home/first_app/web-app/public;
client_max_body_size 32m;
location / {
try_files $uri @unicorn;
}
location @unicorn {
proxy_set_header Client-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass unix:/home/first_app/web-app/tmp/sockets/unicorn.sock;
}
}


Теперь редактируем кофиг самого сервера nginx. Ниже приведен полный файл конфига:
user nobody nogroup;
worker_processes 4;
pid /var/run/nginx.pid;

events {
worker_connections 4096;
# multi_accept on;
}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

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

##
# Logging Settings
##

log_format main '$remote_addr - $remote_user[$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "http_x_forwarded_for"'

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

# gzip_vary on;
gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites/*.conf;
}

#mail {
# # See sample authentication script at:
# # wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }


Теперь нам надо, чтобы nginx запускался автоматически при запуске VDS. Для этого устанавливаем супервайзер runit:
:~ apt-get install runit
:~ mkdir /etc/sv/nginx

Создадим исполняемый файл для запуска nginx:
:~ vi /etc/sv/nginx/run

И напишем туда вот что:
#!/bin/sh
exec 2>&1
exec /usr/sbin/nginx

Делаем его исполняемым:
:~ chmod +x /etc/sv/nginx/run

Проверим заработало ли все это дело:
:~ /etc/sv/nginx/run
:~ ps aux | grep nginx


Если все хорошо вы увидете 4 запущенных worker_process и сервер nginx. Проблемы могут возникнуть только в том случае если на VDS по-умолчанию был установлен Apache. Так было у меня, что естественно означает занятый 80 порт. Смело сносите Apache и убивайте все его процессы. Надеюсь, что у вас все хорошо и мы продолжим. Осталось сделать симлинк для автоматического запуска:
:~ ln -s /etc/sv/nginx/ /etc/service

Поздравляю nginx утановлен и настроен. На все про все при должной снаровке уйдет минуты 2. Нужно еще создать пользователя, из-под которого будет запускаться приложение:
:~ adduser first_app
:~ vi home/itnotes/.bashrc


Дописываем в этот файл:
export RAILS_ENV=production

Установка RVM и RubyGems

В том же терминале продолжаем:
:~ apt-get install curl
:~ bash -s stable < <(curl -s raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
:~ apt-get install build-essential bison openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev
:~ gpasswd -a first_app rvm
:~ apt-get install rubygems
:~ rvm use --create ruby-1.9.2-p318@first_app
:~ rvm ruby-1.9.2-p318@global gem install bundler
:~ mkdir /home/first_app/web-app
:~ apt-get install git-core git-gui git-doc


Здесь мы устанавливаем curl, затем с его помощь ставим rvm, доставляем пачку пакетов, которые пригодятся для компиляции Ruby, работы sqlite и т.д. После этого ставим Rubygems, создаем гемсет для нашего проекта, утанавливаем bundler для всех проектов и создаем папку для нашего приложения в home директории созданного нами пользователя. Устанавливаем Git.
Выходим из рута, завершаем ssh.

Установка Ruby

Заходим под созданным пользоватлем по ssh:
:~ ssh first_app@<IP машины>
:~ rvm install ruby-1.9.2-p318

Выходим и снова заходим под рутом.

БД, Capistrano и Unicorn

В подавляющем большинстве случаев в качестве бд используется mysql, но знаете, мое личное мнение таково, что если проект не большой, а так себе сайтик чего там делает, то не стоит ему юзать такую бд, ему вполне хватит и sqlite. Кроме того, мы сэкономими еще кучу времени. Переехать потом на mysql, если такое вообще понадобится, можно произвести без особых проблем. Поэтому мы не будем настраивать никаких субд, а сразу перейдем к Capistrano.
Допишите в Gemfile приложения:
group :development do
...
gem 'capistrano-deploy', '~> 0.1.1', :require => nil
end
group :production do
...
gem 'unicorn', '~> 3.6.2', :require => nil
end


Создайте в корне проекта Capfile со следующим содержимым:
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set :rvm_ruby_string, '1.9.2'

require 'capistrano-deploy'
use_recipes :git, :rails, :bundle, :unicorn

server '<IP машины>', :web, :app, :db, :primary => true
set :user, 'first_app'
set :deploy_to, '/home/first_app/web-app'
set :repository, 'git@github.com:<репозиторий>'

after 'deploy:update', 'bundle:install'
after 'deploy:restart', 'unicorn:stop'


Тут есть маленький нюанс, если у вас как и у меня git репозиторий находится на github, то надо не забыть из под созданного юзера на VDS сгенерировать rsa ключи. Как это сделать подробно написано на github.com.

В терминале пишем:
:~ mkdir /etc/sv/first_app_unicorn
:~ touch /etc/sv/first_app_unicorn/run
:~ chmod +x /etc/sv/first_app_unicorn/run
:~ vi /etc/sv/first_app_unicorn/run


Пишем в этот файлик вот это:
#!/bin/sh
exec 2>&1
export USER=first_app
export HOME=/home/$USER
export RAILS_ENV=production
UNICORN="/usr/local/rvm/bin/rvm ruby-1.9.2-p318@first_app exec bundle exec unicorn"
UNICORN_CONF=/etc/unicorn/first_app.rb
cd $HOME/web-app
exec chpst -u $USER:$USER $UNICORN -c $UNICORN_CONF


Далее заполняем файл /etc/unicorn/first_app.rb вот этим:
worker_processes 4
working_directory "/home/first_app/web-app"
listen "/home/first_app/web-app/tmp/sockets/unicorn.sock", :backlog => 64
pid "/home/first_app/web-app/tmp/pids/unicorn.pid"
stderr_path "/home/first_app/web-app/log/unicorn.stderr.log"
stdout_path "/home/first_app/web-app/log/unicorn.stdout.log"


Последний рывок:
ln -s /etc/sv/first_app_unicorn /etc/service

Настройка домена

Необходимо добавить 2 записи А типа: для субдомена @ и www, с указанием IP вашего VDS. Хорошо бы это сделать до настройки сервера, тогда пока вы все настроите изменения вступят в силу.

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

Заключение

Для быстрого обновления мелких изменений на сайте я создал такой файлик в корне приложения:
git add .
git commit -a -m "Release"
git push
cap deploy:update
cap deploy:restart


Назвал его deploy и сделал его исполняемым. Теперь чтобы обновить сайт на github и VDS требуется всего одна команда:
:~ ./deploy
Tags:
Hubs:
Total votes 19: ↑13 and ↓6 +7
Views 23K
Comments Comments 22