Установка rails приложения с нуля на ubuntu

В этой заметке я рассмотрю полный цикл развертывания rails приложения на ubuntu-server. Использованный стэк технологий:

  • Ubuntu server
  • Postgresql
  • Nginx
  • RVM
  • Puma
  • Ruby
  • Git
  • Sidekiq
  • Redis
  • Rails
  • Capistrano

Обновляем систему

aptitude udpate
aptitude upgrade

Установим некоторые полезные иструменты

# Git
aptitude install git-core

# Для компиляции различных гемов
aptitude install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake nodejs

# Умный top
aptitude install htop 

# Разные полезные утилиты
aptitude install software-properties-common python-software-properties rsyslog

Если есть проблемы с кодировкой

Добавляем строку LC_ALL="en_US.UTF-8" on /etc/default/locale Выполняем команды locale-gen en_US en_US.UTF-8 && dpkg-reconfigure locales и перезагружаем shutdown -r now

Создаём пользователя, от имени которого будем деплоить

adduser deploy

visudo

root    ALL=(ALL:ALL) ALL

# Эту строку нужно добавить
deploy  ALL=(ALL:ALL) ALL

Настройка доступа по ключу

# Генерация ключа (если еще не создан) на локальной машине
ssh-keygen

# Копируем ключ
ssh-copy-id deploy@host

sudo nano --syntax=sh /etc/ssh/sshd_config
# Закрываем доступ по паролю (Обязательно проверить, что авторизация работает по сертификату!)
PasswordAuthentication no
# Запрещаем рута
PermitRootLogin no

# Перезагружаем
sudo service ssh restart

Установка базы данных

# Добавляем репозиторий
sudo bash -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' >> /etc/apt/sources.list.d/pgdg.list"
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | \
  sudo apt-key add -
sudo aptitude update

# Установка
sudo apt-get install -y postgresql postgresql-client libpq-dev

# Заходим в консоль
sudo -u postgres psql -d template1

# Добавляем пользователя, от которого будем работать с базой
CREATE USER deploy CREATEDB;

Установка Redis

sudo aptitude install tcl
wget http://download.redis.io/releases/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make

# Рекомендуемые тесты
cd src
make test

# Установка
sudo make install

cd .. && cd utils

# Установочный скрипт
sudo ./install_server.sh

При возникновении такой ошибки:

ERROR: heartbeat: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

Лечим так:

sudo nano --syntax=sh /etc/redis/6379.conf
stop-writes-on-bgsave-error no

Закрываем доступ извне к серверу:

sudo nano --syntax=sh /etc/redis/6379.conf
bind 127.0.0.1

# Проверяем можно ли поключится с удаленного сервера:
redis-cli -h IP_SERVER

Установка RVM

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable
source /home/deploy/.rvm/scripts/rvm

# Для примера установим интерпретатор
rvm install 2.2.1
ruby -v

Установка Nginx

sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx

Для правильного определения IP-адреса веб-сервером рейльсов в конфиг /etc/nginx/nginx.conf нужно добавить:

proxy_hide_header X-Frame-options;

Холодный деплой

Перед деплоем нужно скопировать публичный ключ сервера (на котором будет происходить развёртываение) на сервер git (с коротого будет происходить скачивание релиза) cat .ssh/id_rsa.pub

# Создаём каталог на сервере для приложений
mkdir apps

# Запуск проверки на локальном сервере
bundle exec cap production deploy:check

После этого создатся каталоги shared и releases. В shared/config кладём необходимые нам файлы, например конфиг базы данных.

# Делаем полный деплой
bundle exec cap production deploy

Может возникать неприятная ошибка с установкой гема rmagick:

An error occurred while installing rmagick (2.15.0), and Bundler cannot
	continue.
	Make sure that `gem install rmagick -v '2.15.0'` succeeds before bundling.

Лечится она доустановкой дополнительных пакетов в убунту:

sudo aptitude install build-essential imagemagick libmagickcore-dev libmagickwand-dev

Для запуска вспомогательных задач после деплоя, можно исользовать команды типа (например я восстанавливаю таким образом базу и картинки):

bundle exec rake backup:restore RAILS_ENV="production"

Установка Puma

cd ~
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf
nano --syntax=sh puma.conf

Меняем строчки:

setuid deploy
setgid deploy

Копируем sudo cp puma.conf puma-manager.conf /etc/init В файл /etc/puma.conf прописываем: /home/deploy/appname

Запуск приложения

sudo start puma-manager
sudo start puma app=/home/deploy/appname

Настройка Nginx

sudo ln -s /etc/nginx/sites-available/onthehook /etc/nginx/sites-enabled/onthehook
sudo service nginx restart

У меня возникала ошибка вот такая ошибка:

nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
nginx: configuration file /etc/nginx/nginx.conf test failed

Лечится она так: Вносим изменения в конфиг:

http {
    server_names_hash_bucket_size 64;
    ...
}
sudo kill -HUP `cat /var/run/nginx.pid`
sudo service nginx restart

# Проверяем
sudo nginx -t

Пример конфига для nginx:

upstream awesome {
  server unix:/home/deploy/www/awesome/shared/sockets/puma.sock;
}

server {
  listen 0.0.0.0:80;
  server_name www.awesome.ru;
  rewrite  ^/(.*)$  http://awesome.ru/$1 permanent;
}

server {
  listen 0.0.0.0:80 default_server;
  server_name awesome.ru;
  server_tokens off; 
  root /home/deploy/www/awesome/current/public;

  access_log  /var/log/nginx/awesome_access.log;
  error_log   /var/log/nginx/awesome_error.log;

  location / {
    # serve static files from defined root folder;.
    try_files $uri $uri/index.html $uri.html @awesome;
  }

  location @awesome {
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_redirect     off;

    proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header   Host              $host;
    proxy_set_header   X-Real-IP         $remote_addr;

    proxy_pass http://awesome;
  }
}

Конфиг кладём в /etc/nginx/sites-available/awesome и делам сим-линк на него sudo ln -s /etc/nginx/sites-enabled/awesome /etc/nginx/sites-available/awesome