Не так давно мне надо было настраивать новый сервак. В ходе настройки я решил помечать свои действия, чтобы в будущем мне было куда подглядывать и делать это быстро. Полагаю, что эти мои пометки будут полезны и другим. Вот и получилась эта статья. Прошу заметить что данная статья в стадии черновика. Некоторые действия я мог делать в другом порядке, а потом что-то туда-сюда менять. А что-то и вовсе мог забыть пометить. Планирую при следующей настройке сервера привести в порядок эту инструкцию. А пока вот делюсь ею в таком виде =)
Дано: свежеустановленный debian6.
Задача: настроить сервер для работы с ruby on rails. Настроить и задеплоить приложение (у меня оно называлось samohodom).
Средства:
- debian – ОС
- nginx – веб сервер
- unicorn – сервер для запуска rack приложений
- runit – супервайзер, для стопроцентного запуска процессов
- percona server – форк mySQL со всякими патчиками
- rvm – ruby version manager. Позволяет иметь на одном сервере сразу несколько разных версий ruby
- capistrano и capistrano-deploy – для деплоя нашего приложения на сервер
- git – при разработке приложения в качестве системы контроля версий мы используем git. И деплоить будем из репозитория.
Первым делом обновим системку на всякий случай и установим пару необходимых (для меня) пакетов.
apt-get update apt-get upgrade apt-get install vim mc git-core curl
Установка nginx
С оффициального сайта скачиваем последнюю стабильную версию nginx http://sysoev.ru/nginx/download.html
wget http://sysoev.ru/nginx/nginx-1.0.4.tar.gz
Распаковываем и заходим в директорию:
tar xzf nginx-1.0.4.tar.gz cd nginx-1.0.4 ./configure --prefix=/opt/nginx
Если получили ошибку «./configure: error: C compiler gcc is not found», то значит у вас нету компилятора. Для решения стоит поставить целиком метапакет build-essential. Он подтянет по зависимостям и компилятор и прочие нужные штуки для компиляции программ.
apt-get install build-essential
Снова пытаетесь выполнить ./configure для nginx. Если будет ошибка типа такой:
checking for PCRE library ... not found checking for PCRE library in /usr/local/ ... not found checking for PCRE library in /usr/include/pcre/ ... not found checking for PCRE library in /usr/pkg/ ... not found checking for PCRE library in /opt/local/ ... not found ./configure: error: the HTTP rewrite module requires the PCRE library. You can either disable the module by using --without-http_rewrite_module option, or install the PCRE library into the system, or build the PCRE library statically from the source with nginx by using --with-pcre= option.
То выполняем:
apt-get install libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev
Результатом успешной работы ./configure будет что-то типа такого:
Configuration summary + using system PCRE library + OpenSSL library is not used + md5: using system crypto library + sha1: using system crypto library + using system zlib library nginx path prefix: "/opt/nginx" nginx binary file: "/opt/nginx/sbin/nginx" nginx configuration prefix: "/opt/nginx/conf" nginx configuration file: "/opt/nginx/conf/nginx.conf" nginx pid file: "/opt/nginx/logs/nginx.pid" nginx error log file: "/opt/nginx/logs/error.log" nginx http access log file: "/opt/nginx/logs/access.log" nginx http client request body temporary files: "client_body_temp" nginx http proxy temporary files: "proxy_temp" nginx http fastcgi temporary files: "fastcgi_temp" nginx http uwsgi temporary files: "uwsgi_temp" nginx http scgi temporary files: "scgi_temp"
Если ./configure отработал хорошо, то компилим и устанавливаем
make make install
Настраиваем nginx
Конфигурируем nginx следующим образом. Мы сделаем в папке с конфигами папку servers/ в которую будем класть отдельные файлы для каждого проекта на нашем сервере. В основном кофиге nginx мы укажем загрузку всех файлов *.conf из этой директории.
Вот какие у меня получились конфиги:
/opt/nginx/conf/nginx.conf
daemon off;
user nobody nogroup;
worker_processes 2; # нету смысла ставить больше, чем ядер процессора в сервере
#error_log /var/log/nginx/error.log info;
events {
worker_connections 4096; # количество соединений на каждый рабочий процесс
}
http {
include mime.types;
default_type application/octet-stream;
#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 logs/access.log main;
sendfile on;
keepalive_timeout 65;
include gzip.conf;
server_names_hash_max_size 262144;
server_names_hash_bucket_size 128;
include servers/*.conf;
}
/opt/nginx/conf/gzip.conf
gzip on; gzip_http_version 1.0; gzip_proxied any; gzip_types text/plain text/xml text/css text/javascript application/x-javascript application/xml application/xml+rss;
/opt/nginx/conf/servers/samohodom.conf
server {
listen 80;
server_name samohodom.com;
root /home/samohodom/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 http://unix:/home/samohodom/web-app/tmp/sockets/unicorn.sock;
}
}
Теперь делаем запуск nginx через супервайзер runit.
apt-get install runit mkdir /etc/sv/nginx
Создаём файлик /etc/sv/nginx/run с вот таким содержимым:
#!/bin/sh exec 2>&1 exec /opt/nginx/sbin/nginx
Делаем его исполняемым:
chmod +x /etc/sv/nginx/run
Теперь для теста можно выполнить этот файл и проверить, что теперь ваше приложение отвечает на 80 порту.
/etc/sv/nginx/run
Затем для останова выполнения этого файла нажмите Ctrl+c.
Теперь делаем симлинку, чтобы runit его запускал:
ln -s /etc/sv/nginx/ /etc/service
Сразу после этого runit должен запустить nginx. Проверить можно вот так:
root@domU-12-31-39-0A-19-93:~# ps aux | grep nginx root 18977 0.0 0.0 164 4 ? Ss 15:04 0:00 runsv nginx root 18978 0.0 0.3 27812 1968 ? S 15:04 0:00 nginx: master process /opt/nginx/sbin/nginx nobody 18979 0.0 0.4 29392 2464 ? S 15:04 0:00 nginx: worker process nobody 18980 0.0 0.4 29392 2464 ? S 15:04 0:00 nginx: worker process root 18988 0.0 0.1 7928 1068 pts/0 S+ 15:05 0:00 grep --color=auto nginx
Вот пара полезных команд:
- sv status nginx – проверка статуса
- sv up nginx – запустить nginx
- sv down nginx – остановить nginx
Создаём пользователя для приложения
adduser samohodom
В home директории этого пользователя в файл .bashrc добавляем
export RAILS_ENV=production
Это чтобы когда мы на серваке при необходимости будем самостоятельно писать rails console или rails db:reset, то чтобы окружение использовалось не development, а production.
Устанавливаем rvm под root
Нам понадобится curl. Если его в системе нет, то устанавливаем:
apt-get install curl
Инструкции по установке rvm смотрим в первую очередь на оффициальном сайте: https://rvm.beginrescueend.com/rvm/install/
В моём случае это выглядело вот так:
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
В конце установки rvm напишет какие пакеты вам надо установить для разных интерпретаторов ruby. Мы, конечно, используем обычный ruby, а не какой-нибудь там ironruby или jruby. В моём случае мне rvm подсказал вот такую строчку:
apt-get install build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev
Так же нам надо добавить пользователя, который будет работать с rvm в группу rvm:
gpasswd -a samohodom rvm
Теперь можно зайти под нашим новым пользователем и запустить установку ruby. Для моего проекта нужен 1.9.2:
rvm install ruby-1.9.2-p180
MySQL
В качестве mysql сервера мы решили использовать percona-server. Этот тот же mysql, но с кое-какими патчами и улучшениями. В работе он абсолютно такой же как mysql.
Инструкции по его установке смотрите на оффициальном сайте: http://www.percona.com/
В моём случае это выглядело вот так. Добавляем ключи и репозитории перконы как описано тут (http://www.percona.com/docs/wiki/repositories:apt)
gpg --keyserver hkp://keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A gpg -a --export CD2EFD2A | apt-key add -
В /etc/sources.list добавляем:
deb http://repo.percona.com/apt squeeze main deb-src http://repo.percona.com/apt squeeze main
apt-get update
Устанавливаем сам сервер (http://www.percona.com/docs/wiki/percona-server:installation:from-repositories#installation_on_apt-based_systems):
apt-get install percona-server-server apt-get install libmysqlclient-dev
Создаём mysql пользователя и базу данных. Для этого входим в mysql консоль:
mysql -uroot -p
После ввода пароля попадаем в mysql консоль, где пишем примерно следующее (звёздочки заменяем на пароль для пользователя):
CREATE USER 'samohodom'@'localhost' IDENTIFIED BY '**********'; CREATE DATABASE IF NOT EXISTS `samohodom` CHARACTER SET 'utf8'; GRANT ALL PRIVILEGES ON `samohodom` . * TO 'samohodom'@'localhost';
Настройка деплоя приложения через capistrano
Мы для деплоя используем capistrano. Но только не совсем в оригинальном виде, а с гемом capistrano-deploy.
В корень проекта кладём файлик Capfile cо следующим содержимым:
$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) # Add RVM's lib directory to the load path.
require "rvm/capistrano" # Load RVM's capistrano plugin.
set :rvm_ruby_string, '1.9.2@samohodom' # Or whatever env you want it to run in.
require 'capistrano-deploy'
use_recipes :git, :rails, :bundle, :unicorn
server 'samohodom.com', :web, :app, :db, :primary => true
set :user, 'samohodom'
set :deploy_to, '/home/samohodom/web-app'
set :repository, 'git@********.net:samohodom.git'
after 'deploy:update', 'bundle:install'
after 'deploy:restart', 'unicorn:stop'
Первые три строки необходимы для интеграции с rvm и подсомотрены вот тут: https://rvm.beginrescueend.com/integration/capistrano/
Теперь настроим запуск нашего приложения через unicorn. А после этого можно будет задеплоить.
Настриваем unicorn
Во-первых в Gemfile приложения добавляем:
group :production do gem 'unicorn', '~> 3.6.2', :require => nil end group :development do gem 'capistrano-deploy', '~> 0.1.1', :require => nil end
Затем я на серваке создал гемсет для проекта и папку для него, а так же установил bundler в глобальный гемсет (т.е. он будет виден во всем гемсетах внутри этой версии руби)
rvm use --create ruby-1.9.2-p180@samohodom rvm 1.9.2@global gem install bundler
Выполняем
cap deploy:setup
Кстати если на серваке нужна java (например мне она нужна для гема jammit), то рекомендую ставить sun-java6-jdk. Она находится в contrib или non-free репозитори
Для этого в /etc/apt/sources.list строки
deb http://ftp.us.debian.org/debian squeeze main deb http://security.debian.org squeeze/updates main
заменяем на:
deb http://ftp.us.debian.org/debian squeeze main contrib non-free deb http://security.debian.org squeeze/updates main contrib non-free
Затем обновляем списки пакетов и устанавливаем java:
apt-get update apt-get install sun-java6-jdk
Далее настраиваем запуск unicorn через runsv:
mkdir /etc/sv/samohodom_unicorn touch /etc/sv/samohodom_unicorn/run chmod +x /etc/sv/samohodom_unicorn/run
В файле /etc/sv/samohodom_unicorn/run следующее содержимое:
#!/bin/sh exec 2>&1 export USER=samohodom export HOME=/home/$USER export RAILS_ENV=production UNICORN="/usr/local/rvm/bin/rvm 1.9.2@samohodom exec bundle exec unicorn" UNICORN_CONF=/etc/unicorn/samohodom.rb cd $HOME/web-app exec chpst -u $USER:$USER $UNICORN -c $UNICORN_CONF
Как видно мы тут указали конфиг для unicorn для нашего приложения /etc/unicorn/samohodom.rb
Создаём директорию (если нету) и кладём туда файлик с содержимым:
worker_processes 4 # это число процессов, которые будут запускаться для unicorn. Если памяти мало, то лучше ставьте поменьше. Можно для начала 1 установить. working_directory "/home/samohodom/web-app" listen "/home/samohodom/web-app/tmp/sockets/unicorn.sock", :backlog => 64 pid "/home/samohodom/web-app/tmp/pids/unicorn.pid" stderr_path "/home/samohodom/web-app/log/unicorn.stderr.log" stdout_path "/home/samohodom/web-app/log/unicorn.stdout.log"
Так же удостоверьтесь, что у вас на серваке в папке с проектом есть директории tmp/pids/ и tmp/sockets/
Вроде с конфигами unicorn всё. Тут не спешим делать симлинку для автоматического запуска через runsv, а сперва пробуем запустить вручную:
/etc/sv/samohodom_unicorn/run
Пробуем открыть в браузере. Надо будет немного подождать чтобы все воркеры стартанули. Время их старта зависит от количества оперативы и процессора. Если долго не стартует, то в файле /etc/unicorn/samohodom.rb установите «worker_processes 1″.
Если всё заработало, то делаем симлинку для runsv на запуск unicorn, чтобы runit его запускал.
ln -s /etc/sv/samohodom_unicorn /etc/service
Если по каким-то причинам что-то не работает с unicorn и вы хотите это найти, то можно:
1. остановить запуск unicorn через runsv (sv down samohodom_unicorn) и запустить напрямую /etc/sv/samohodom_unicorn/run и посмотреть что напишет. Если ничего не напишет, то можно попробовать второй способ.
2. Кладём файлик /etc/sv/samohodom_unicorn/log/run с таким содержимым:
#!/bin/sh LOG_FOLDER=/var/log/samohodom_unicorn mkdir -p $LOG_FOLDER exec svlogd -tt $LOG_FOLDER
Далаем этот файл исполняемым.
Перезапустите unicorn и посмотрите загляните в папку с логами (/var/log/samohodom_unicorn).
у меня после make выдается вот такая канатель
make[1]: Leaving directory `/root/nginx-1.0.4′
не подскажите как исправить ?
Link | Июль 19th, 2011 at 20:39
если мне не изменяет память, то так и должно быть. Тут же не пишет об ошибках. Пробуйте дальше выполнить «make install»
Link | Июль 20th, 2011 at 10:27
продолжил, теперь после
/opt/nginx/conf/nginx.conf
выдает
-bash: /opt/nginx/conf/nginx.conf: Permission denied
после /opt/nginx/conf/gzip.conf
выдает
-bash: /opt/nginx/conf/gzip.conf: No such file or directory
а после exec /opt/nginx/sbin/nginx
вообще закрылся ssh клиент ( Putty)
Link | Июль 21st, 2011 at 20:44
видимо не видать мне руби как своих ушеи (
Link | Июль 21st, 2011 at 20:44
Похоже на то, что у вас нет прав. Запустите make install от привелигированного пользователя.
Автору спасибо, в ближайшее время как раз займусь деплойментом, читаю все подходящие статьи.
Link | Июль 25th, 2011 at 04:07
sudo /etc/sv/nginx/run
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
Что не так((
Link | Ноябрь 1st, 2011 at 19:54
Не подскажете, почему у меня не работает управление nginx через sv. При команде например sv status nginx выдает:
fail: nginx: unable to change to service directory: file does not exist
Настраивал все прямо по этой инструкции.
Спасибо.
Link | Ноябрь 17th, 2011 at 15:02
@Bms у тебя значит уже работает nginx на 80 порту, либо стоит апач и занят 80 порт
Link | Ноябрь 22nd, 2011 at 21:52
Сначала вы писали:
Мы сделаем в папке с конфигами папку sites/
а потом есть строчка:
/opt/nginx/conf/servers/samohodom.conf
неувязка маленькая (8
Link | Декабрь 20th, 2011 at 08:37
спасибо, поправил
Link | Декабрь 23rd, 2011 at 23:41
не рекомендую RVM использовать на продакшене
Link | Январь 21st, 2012 at 09:44
2Dan: почему же? как раз-таки rvm и разрабатывался в первую очередь для использования на production. И с ним действительно довольно удобно на серваке. Особенно выручает в случаях когда на серваке несколько рельсовых проектов на разных версиях руби. Так что я как раз за то, чтобы использовать на продакшене именно RVM!
Link | Январь 21st, 2012 at 10:13
ещё вот добавлю: мой хостер http://locum.ru где я покупаю обычный shared хостинг но для rails приложений раньше не использовали RVM, а потом перешли именно на RVM. А у них там куча проектов крутится от разных юзеров с разными версиями рельс, с разными версиями гемов и прочее, прочее…
Link | Январь 21st, 2012 at 10:16
мне показалось, или вы упустили установку рельс…
Link | Январь 27th, 2012 at 06:04
2f1aky: вроде нет, не упустил. при сетапе деплоя через капистрано (не помню точно при именно при сетапе или просто при деплое там вызывается установка гемов) поставятся как рельсы, так и остальные гемы из Gemfile проекта.
Link | Январь 27th, 2012 at 17:14