Быстрое развертывание Rails 5 с PostgreSQL и Nginx на Ubuntu 16.04

С использованием Foreman и systemd

Andrey Viktorov
Sibdev
6 min readNov 14, 2017

--

В теории, этот гайд будет работать и для Ubuntu 14.04, но лучше не рисковать и обзавестись сервером с 16.04.

Внимание! Гайд рассчитан на то, что все действия вы будете производить на чистом сервере

Что мы сделаем:

  • Создадим отдельного нерутового пользователя
  • Установим и настроим postgres
  • Установим Ruby и зависимости
  • Настроим Foreman и переменные окружения
  • Настроим Nginx
  • С помощью Foreman настроим systemd-сервисы

Шаг нулевой: Доставляем приложение на сервер

Я для этого использую так называемые “Deploy keys” в Gitlab/Github/Bitbucket. Они позволяют сгенерировать на сервере ssh-ключ и использовать его для клонирования проекта.

Здесь один важный момент: НИКОГДА не клонируйте проект в домашнюю папку рутового пользователя (/root). Я все свои проекты держу в /var/www (главное убедитесь, что он не светит именно этой папкой в интернеты через apache/nginx)

Шаг первый: Отдельный пользователь

Для начала, заведем специального пользователя, от чьего имени будет запускаться наше приложение:

Флаг -r означает “системный аккаунт”: у этого пользователя не будет домашней папки и входа по паролю. Он нужен для того, чтобы не запускать приложение от root.

Имя пользователя может быть любое, но я выбрал railsuser. В дальнейшем, везде в гайде будет фигурировать именно оно.

PostgreSQL

Теперь установим и настроим постгрес:

Для начала, коль у нас чистый сервер, обновим пакеты:

Затем, поставим постгрес и библиотеки, необходимые для рельс:

Теперь, создадим пользователя в postgresql. Имя ему дадим такое же, как и у пользователя для запуска приложения:

Это создаст пользователя (роль в терминах postgres) railsuser с правами на создание баз данных.

Теперь разрешим ему беспарольный вход из под localhost:

Откроем файл /etc/postgresql/9.5/main/pg_hba.conf в каком-нибудь консольном редакторе (например, nano или vim), и в разделе “put your actual configuration here” напишем следующее:

Перезапустим постгрес:

Проверим:

Если мы видим сообщение о том, что БД не существует, значит все ок. Если видим запрос пароля — значит не всё ок.

Ruby и другие нужные штуки

Если вы так же как я разворачиваете все приложения на отдельные сервера, то ruby лучше поставить через apt.

Для этого воспользуемся репозиториями Brightbox:

Здесь можно почитать о них подробнее: https://www.brightbox.com/docs/ruby/ubuntu/

Установим штуку, упрощающую подключение ppa:

Подключим ppa и обновим репозитории:

Теперь установим Ruby. Например, мне нужна Ruby 2.4 (второй пакет нужен для сборки зависимостей)

Теперь установим Node.js (он нужен для сборки ассетов). Воспользуемся репо nodesource (подробнее: https://github.com/nodesource/distributions)

Ставить будем последнюю из существущих на данный момент LTS: 8.9

Теперь поставим bundler:

Procfile, права на папку

Теперь пора внести некоторые изменения в приложение.

Для работы с переменными откружения мы будем использовать файл .env

Для начала, внесите .env в .gitignore

Затем, напишем Procfile:

Подробно о формате Procfile можно почитать на Heroku: https://devcenter.heroku.com/articles/procfile

Для Rails он будет выглядеть примерно так:

Обратите внимание на $PORT. Оно должно выглядеть именно так, туда в дальнейшем foreman подставит номер порта.

Запушим Procfile и изменения в .gitignore в git и склонируем их на сервер.

Затем, выдадим права на папку с нашим приложением нашему пользователю:

Где deploy/ — это имя папки

Установка зависимостей

Теперь нам нужно установить некоторые пакеты для запуска rails:

Теперь установим зависимости нашего приложения:

Настройка .env

Создадим файл .env и напишем туда нужные нам вещи:

SECRET_KEY_BASE мы можем сгенерировать, запустив эту команду в папке приложения:

Учтите, что ваше приложение должно быть настроено для работы с DATABASE_URL. Если вы пользуетесь новой версией Rails, скорее всего, оно будет работать “из коробки”.

Foreman

Установим foreman:

После установки, временно подредактируем наш Procfile, добавив к запуску сервера флаг -b 0.0.0.0 . Он нужен, чтобы мы могли протестировать наше приложение без nginx. Позже мы его уберем

Пробуем запустить сервер:

И… запустился!

Заходим на нашайпи:5000 и смотрим в логах, что ему не хватает

А не хватает ему БД и статики

БД, миграции, ассеты

Чтобы при запуске команды подхватывали наши переменные окружения, запускать их нужно через foreman run

Для начала, создадим БД:

Затем, запустим миграции:

Seeds:

Прекомпилируем ассеты:

Заходим на наше приложение и… все равно не видим статики. Почему?

Потому что rails в продакшн-режиме по-умолчанию настроен на то, что статику за него будет отдавать кто-нибудь другой. У нас этим “кто-нибудь другой” будет Nginx.

Nginx

Для начала, приведем Procfile к исходному виду, убрав -b 0.0.0.0 , так как нам больше не надо, чтобы приложение слушало не-локальные порты.

Теперь установим Nginx:

Затем, в папке /etc/nginx/sites-available создадим файл с именем, равным имени нашего домена (не забудьте настроить A-запись на ваш сервер!). У меня это demotest.andv.xyz

Содержимое у него должно быть примерно такое:

Где:

/var/www/apps/deploy/public; — путь к папке public вашего приложения

demotest.andv.xyz — ваш домен

UPD 11.07.18: Добавлен X-Forwarded-Proto, чтобы не возникало вечного редиректа при включенном force_ssl

Можно запустить сервер и посмотреть, всё ли ок

Systemd

Остался последний штрих: сделать так, чтобы нам не приходилось запускать сервер в терминале, а его запуском руководил systemd.

Заведём в нашем репо папку scripts, в которой напишем один полезный скрипт по имени update-services-and-restart.sh :

В трех переменных нам нужно указать:

app_name— имя приложения

app_port — порт, кратный 1000 (не меньше 2000)

app_user — имя пользователя, от которого будет запущено приложение

Если вы ничего не меняли порт в конфиге nginx и имя пользователя, то вам нужно указать только app_name

Выдаем права на запуск:

Коммитим, пуляем на сервере, УБИРАЕМ -b 0.0.0.0 ИЗ Procfile, запускаем (при выключенном сервере rails).

При каждом изменении Procfile вам нужно будет заново запускать этот скрипт, это важно!

Заходим на домен и видим приложение.

А если не видим — пишем journalctl -f --lines 500 и смотрим, что сломалось.

Отдельно про foreman run

В конце хочу напомнить про то, что все команды rails, которым нужно знать текущее окружение (например, rails console или rails db:migrate) теперь нужно запускать через foreman run.

--

--