Деплой Rails приложения на DigitalOcean

Долгие ночи ты писал код своего супер приложения на Ruby on Rails. Готов ли ты к тому, чтобы его увидел весь мир? Пора тебе уже выйти из development режима и опробовать наконец production версию твоего приложения.

Сегодня мы настроим свежекупленный VPS под нужды наших Rails приложений и развернем на него тестовое приложение. Статья будет состоять из 4-х частей:

  1. Предподготовка
    1.1 Создание SSH ключа
    1.2 Добавление ключа в профиль на DO
  2. Создание дроплета
  3. Настройка дроплета
    3.1 Безопасность
    3.2 Установка русской локали
    3.3 Обновление системы
    3.4 Установка RVM и Ruby
    3.5 Установка MySQL
    3.6 Установка Node.js
    3.7 Установка NGINX
  4. Деплой Rails приложения
    4.1 Создание тестового приложения
    4.2 Деплой нашего приложения

В статье я буду работать с VPS купленным у DigitalOcean.

DigitalOcean предлагает самые демократические цены на виртуальные сервера с хорошим пингом даже из России. Кстати, ребята часто раздают промо коды для получения средств на оплату услуг.

1.Предподготовка

Перед покупкой дроплета я рекомендую содать SSH ключ для связки нашего компьютера и покупаемого дроплета.

1.1 Создание SSH ключа

Переходим в директорию SSH ключей

$ cd ~/.ssh

Создадим новый ключ для DigitalOcean

```$ ssh-keygen -t rsa -C “[email protected]” Generating public/private rsa key pair.


В процессе генерации нужно указать название ключа:

Enter file in which to save the key (/home/username/.ssh/id_rsa):digital_ocean_rsa


Далее следует ввести пароли для ключей, но мы смело пропустим их нажав Enter.

Enter passphrase (empty for no passphrase): Enter same passphrase again:


Генерация ключа должна закончиться вот таким вот сообщением:

Your identification has been saved in digital_ocean_rsa. Your public key has been saved in digital_ocean_rsa.pub. The key fingerprint is: 5e:72:rd:01:c4:36:84:23:ef:45:5b:ef:5z:e2:72:74 [email protected] The key’s randomart image is: +–[ RSA 2058]—-+ | pp. | | . x.+ | | = =.p | | . R.-,+. | | S+d=.,.. | | ..++ . | | .p | | | | | +—————–+


### 1.2 Добавление ключа в профиль на DO 

Скопируем созданный ключ:

$ xclip -sel clip < ~/.ssh/digital_ocean_rsa.pub


Все, ключ в буфере обмена. Можно смело идти в раздел [SSH Keys][3] панели управления DO и и добавить наш ключ. На этом предподготовку можно считать завершенной

* * *

## 2. Создание дроплета 

Переходим в Droplets -> [Create Droplet][4]

Выбираем опции для дроплета:

  * имя дроплета;
  * тарифную опцию(5-ти долларовый нам вполне сойдет);
  * регион, где будет располагаться дроплет;
  * дистрибутив устанавливаемого linux;
  * выбор импортируемого SSH ключа.

 

После выбора нужных пунктов смело нажимаем кнопку Create Droplet и через некоторое время нас перекидывает вот в такую симпатичную панель управления дроплетом.  
После создания дроплета, root доступ к машине будет возможен только по ssh ключу, т.к. мы его подключили при создании дроплета. Впрочем скоро мы отключим root доступ из соображений безопасности.

* * *

## 3. Настройка дроплета 

Итак, у нас есть дроплет, пора бы соединиться с ним.  
IP своего сервера можно посмотреть в самом верху панели управления дроплетом.

ssh [email protected]


Если все хорошо, то видим нечто подобное:

[email protected]:~#


Отлично, теперь нужно позаботиться о безопасности дроплета.

### 3.1 Безопасность 

#### Добавление пользователя 

adduser username


Отвечаем на вопросы, подтверждаем информацию и пользователь готов.

Теперь дадим ему нормальные права

visudo


Находим следующие строки:

User privilege specification

root ALL=(ALL:ALL) ALL


И прямо под рутом добавляем своего пользователя с такими же правами

username ALL=(ALL:ALL) ALL


Сохраняемся и выходим из редактора.


#### Смена порта SSH 

nano /etc/ssh/sshd_config


Находим строку:

Port 22


И «22» поменяем на какой нибудь другой порт по своему желанию(1025..65536):

Port 6629


#### Отключение входа root пользователем 

В этом же файле находим строку PermitRootLogin и ставим ей значение ‘no’:

PermitRootLogin no


И в конец самого файла добавляем строчки

UseDNS no AllowUsers username


Сохраняемся и выходим из редактора.

Перезагружаем SSH

reload ssh


Теперь, создадим новую вкладку в терминале и попробуем соединиться

ssh -p 6629 [email protected]


Завершаем ssh соединение, чтобы скопировать ssh ключ с локального компьютера.

$ cat ~/.ssh/igital_ocean_rsa.pub | ssh -p 6629 [email protected] “mkdir -p ~/.ssh && cat » ~/.ssh/authorized_keys”


Если все прошло успешно, то пробуем заново залогиниться на сервере:

$ ssh -p 6629 [email protected]


Если система не спрашивает у нас пароль то проедыдущий шаг мы сделали правильно.

На этом настройки безопасности не завершены, но к ним мы вернемся в конце этой статьи.

## 3.2 Установка русской локали 

Если вам неспокойно от того что время от времени могут появляться сообщения такого рода:

locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory


то рекомендую поставить русскую локаль.

$ localedef ru_RU.UTF-8 -i ru_RU -fUTF-8


после этого вы на всегда забудете об ожибках локалейи и вам будет доступен ввод уириллицы из консоли.

## 3.3 Обновление системы 

Обновление системы рекомендуется делать сразу же после первой авторизации на сервере, но и сейчас не поздно сделать это.

$ sudo apt-get update $ sudo apt-get upgrade


### 3.4 Установка RVM и Ruby 

#### RVM 

$ \curl -sSL https://get.rvm.io | bash -s stable $ source /home/username/.rvm/scripts/rvm


#### Установка всех зависимостей, которые могут пригодиться:

$ rvm requirements


во время выполнения этой команды установятся следующие пакеты: `gawk, g++, gcc, make, libc6-dev, libreadline6-dev, zlib1g-dev, libssl-dev, libyaml-dev, libsqlite3-dev, sqlite3, autoconf, libgdbm-dev, libncurses5-dev, automake, libtool, bison, pkg-config, libffi-dev`

#### Ruby 2.0.0: 

rvm install 2.0.0 && rvm use 2.0.0 –default


#### Установка последней версии RubyGems

$ rvm rubygems current


### 3.5 Установка MySQL 

$ sudo apt-get install mysql-server mysql-client libmysqlclient-dev


### 3.6 Установка Node.js 

Установку Node.js будем проводить с помощью NVM


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
<span class="gp">$ </span>nvm install node
<span class="gp">$ </span>node --version
v6.0.0</code></pre></figure>



<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span><span class="nv">n</span><span class="o">=</span><span class="k">$(</span>which node<span class="k">)</span>;<span class="nv">n</span><span class="o">=</span><span class="k">${</span><span class="nv">n</span><span class="p">%/bin/node</span><span class="k">}</span>; chmod -R 755 <span class="nv">$n</span>/bin/<span class="k">*</span>; sudo cp -r <span class="nv">$n</span>/<span class="o">{</span>bin,lib,share<span class="o">}</span> /usr/local</code></pre></figure>


### 3.7 Установка NGINX 

$ sudo apt-get install nginx $ sudo service nginx start


Все, nginx запущен, проверить работу nginx можно набрав IP адрес нащего дроплета в браузере.

Настройка сервера закончена пора приступать к разворачиванию приложения.

* * *

## 4. Деплой Rails приложения 

### 4.1 Создание тестового приложения 

Отсоединимся от сервера и в директории с нашими разработками создадим тестовое приложение

$ rails new testapp -d mysql


$ git init $ git add . $ git commit -m “initial commit” $ git remote add origin https://github.com/istickz/testapp.git


#### Изменим конфигурацию доступа к MySQL и удалим секцию production. 

testapp/config/database.yml


<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"> 
<span class="s">development</span><span class="pi">:</span>
  <span class="s">adapter</span><span class="pi">:</span> <span class="s">mysql2</span>
  <span class="s">encoding</span><span class="pi">:</span> <span class="s">utf8</span>
  <span class="s">database</span><span class="pi">:</span> <span class="s">testapp_development</span>
  <span class="s">pool</span><span class="pi">:</span> <span class="s">5</span>
  <span class="s">username</span><span class="pi">:</span> <span class="s">root</span>
  <span class="s">password</span><span class="pi">:</span> <span class="s">121212</span>
  <span class="s">socket</span><span class="pi">:</span> <span class="s">/var/run/mysqld/mysqld.sock</span>

<span class="s">test</span><span class="pi">:</span>
  <span class="s">adapter</span><span class="pi">:</span> <span class="s">mysql2</span>
  <span class="s">encoding</span><span class="pi">:</span> <span class="s">utf8</span>
  <span class="s">database</span><span class="pi">:</span> <span class="s">testapp_test</span>
  <span class="s">pool</span><span class="pi">:</span> <span class="s">5</span>
  <span class="s">username</span><span class="pi">:</span> <span class="s">root</span>
  <span class="s">password</span><span class="pi">:</span> <span class="s">121212</span>
  <span class="s">socket</span><span class="pi">:</span> <span class="s">/var/run/mysqld/mysqld.sock</span></code></pre></figure>


Секцию production я предлагаю вынести в отдельный файл:

config/production_database.yml


<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"> 
<span class="s">production</span><span class="pi">:</span>
  <span class="s">adapter</span><span class="pi">:</span> <span class="s">mysql2</span>
  <span class="s">encoding</span><span class="pi">:</span> <span class="s">utf8</span>
  <span class="s">database</span><span class="pi">:</span> <span class="s">testapp</span>
  <span class="s">pool</span><span class="pi">:</span> <span class="s">5</span>
  <span class="s">username</span><span class="pi">:</span> <span class="s">someuser</span>
  <span class="s">password</span><span class="pi">:</span> <span class="s">somepassword</span>
  <span class="s">socket</span><span class="pi">:</span> <span class="s">/var/run/mysqld/mysqld.sock</span></code></pre></figure>
   

и добавить в файл .gitignore

$ echo “config/production_database.yml” .gitignore $ git add .gitignore $ git commit -m “ignore database configuration for production”


После чего, занесем изменения в коммит.

$ git add /config/database.yml $ git commit -m “configure only for test and development”


#### Добавим немного фунциональности нашему приложению. 

Пусть наше приложение будет блогом:

$ rails g scaffold Post title:string description:text


Далее добавим страницу открываемую по умолчанию:

testapp/config/routes.rb


<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Testapp</span><span class="o">::</span><span class="no">Application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
  <span class="n">resources</span> <span class="ss">:posts</span>

  <span class="n">root</span> <span class="s1">'posts#index'</span>
<span class="k">end</span></code></pre></figure>


Создадим базу данных и накатим миграции:

$ rake db:create $ rake db:migrate


Пока изменений не накопилось достаточно много, нужно их закоммитить.

$ git add config/routes.rb $ git commit -m “now posts is a root page” $ git add . $ git commit -m “add posts” $ git push origin master


### 4.2 Деплой нашего приложения 

#### Capistrano

Разворачиванием нашего приложения будет заниматься [Capistrano][6]

В Gemfile добавим следующие строки:


<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">group</span> <span class="ss">:development</span> <span class="k">do</span>
  <span class="n">gem</span> <span class="s1">'rvm-capistrano'</span>
  <span class="n">gem</span> <span class="s1">'capistrano'</span>
<span class="k">end</span>

<span class="n">group</span> <span class="ss">:production</span> <span class="k">do</span>
  <span class="n">gem</span> <span class="s1">'unicorn'</span>
<span class="k">end</span></code></pre></figure>


Сapistrano будет отвечать за выполнение команд, а unicorn у нас будет в качестве сервера приложения.

Делаем

$ bundle install $ git commit -am “add unicorn and capistrano gems”


И создаем файлы конфигурации для Capistrano:


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>capify .
<span class="o">[</span>add] writing <span class="s1">'./Capfile'</span>
<span class="o">[</span>add] writing <span class="s1">'./config/deploy.rb'</span>
<span class="o">[</span><span class="k">done</span><span class="o">]</span> capified!
<span class="gp">$ </span><span class="nb">echo</span> <span class="s2">"/config/deploy.rb"</span>  .gitignore
<span class="gp">$ </span>git commit -am <span class="s2">"ignore deploy configuration"</span></code></pre></figure>


Теперь нужно создать еще несколько конфигурационных файлов:

$ touch config/nginx.conf $ touch config/unicorn.rb $ touch config/unicorn_init.sh


* * *

#### Редактирование конфигурационных файлов 

/Capfile


<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby">    
<span class="nb">load</span> <span class="s1">'deploy'</span>
<span class="nb">load</span> <span class="s1">'deploy/assets'</span>
<span class="nb">load</span> <span class="s1">'config/deploy'</span></code></pre></figure>

    

/config/deploy.rb


<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"rvm/capistrano"</span>
<span class="nb">require</span> <span class="s2">"bundler/capistrano"</span>

<span class="n">set</span> <span class="ss">:application</span><span class="p">,</span> <span class="s2">"testapp"</span>
<span class="n">set</span> <span class="ss">:shared_children</span><span class="p">,</span> <span class="n">shared_children</span>
<span class="n">set</span> <span class="ss">:repository</span><span class="p">,</span>  <span class="s2">"[email protected]:istickz/testapp.git"</span>
<span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s2">"/var/www/testapp"</span>
<span class="n">set</span> <span class="ss">:scm</span><span class="p">,</span> <span class="ss">:git</span>
<span class="n">set</span> <span class="ss">:branch</span><span class="p">,</span> <span class="s2">"master"</span>
<span class="n">set</span> <span class="ss">:user</span><span class="p">,</span> <span class="s2">"username"</span>
<span class="n">set</span> <span class="ss">:group</span><span class="p">,</span> <span class="s2">"username"</span>
<span class="n">set</span> <span class="ss">:use_sudo</span><span class="p">,</span> <span class="kp">false</span>
<span class="n">set</span> <span class="ss">:rails_env</span><span class="p">,</span> <span class="s2">"production"</span>
<span class="n">set</span> <span class="ss">:deploy_via</span><span class="p">,</span> <span class="ss">:copy</span>
<span class="n">set</span> <span class="ss">:ssh_options</span><span class="p">,</span> <span class="p">{</span> <span class="ss">:forward_agent</span> <span class="o">=&gt;</span> <span class="kp">true</span><span class="p">,</span> <span class="ss">:port</span> <span class="o">=&gt;</span> <span class="mi">6629</span> <span class="p">}</span>
<span class="n">set</span> <span class="ss">:keep_releases</span><span class="p">,</span> <span class="mi">5</span>
<span class="n">default_run_options</span><span class="p">[</span><span class="ss">:pty</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
<span class="n">server</span> <span class="s2">"XX.XX.XX.XX"</span><span class="p">,</span> <span class="ss">:app</span><span class="p">,</span> <span class="ss">:web</span><span class="p">,</span> <span class="ss">:db</span><span class="p">,</span> <span class="ss">:primary</span> <span class="o">=&gt;</span> <span class="kp">true</span>

<span class="n">after</span> <span class="s2">"deploy"</span><span class="p">,</span> <span class="s2">"deploy:cleanup"</span>

<span class="n">namespace</span> <span class="ss">:deploy</span> <span class="k">do</span>
  <span class="sx">%w[start stop restart]</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">command</span><span class="o">|</span>
    <span class="n">desc</span> <span class="s2">"</span><span class="si">#{</span><span class="n">command</span><span class="si">}</span><span class="s2"> unicorn server"</span>
    <span class="n">task</span> <span class="n">command</span><span class="p">,</span> <span class="ss">roles: :app</span><span class="p">,</span> <span class="ss">except: </span><span class="p">{</span><span class="ss">no_release: </span><span class="kp">true</span><span class="p">}</span> <span class="k">do</span>
      <span class="n">run</span> <span class="s2">"/etc/init.d/unicorn_</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">command</span><span class="si">}</span><span class="s2">"</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="n">task</span> <span class="ss">:setup_config</span><span class="p">,</span> <span class="ss">roles: :app</span> <span class="k">do</span>
    <span class="n">sudo</span> <span class="s2">"ln -nfs </span><span class="si">#{</span><span class="n">current_path</span><span class="si">}</span><span class="s2">/config/nginx.conf /etc/nginx/sites-enabled/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">"</span>
    <span class="n">sudo</span> <span class="s2">"ln -nfs </span><span class="si">#{</span><span class="n">current_path</span><span class="si">}</span><span class="s2">/config/unicorn_init.sh /etc/init.d/unicorn_</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">"</span>
    <span class="n">run</span> <span class="s2">"mkdir -p </span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">/config"</span>
    <span class="n">put</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"config/production_database.yml"</span><span class="p">),</span> <span class="s2">"</span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">/config/database.yml"</span>
    <span class="nb">puts</span> <span class="s2">"Теперь вы можете отредактировать файлы в  </span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">."</span>
  <span class="k">end</span>
  <span class="n">after</span> <span class="s2">"deploy:setup"</span><span class="p">,</span> <span class="s2">"deploy:setup_config"</span>

  <span class="n">task</span> <span class="ss">:symlink_config</span><span class="p">,</span> <span class="ss">roles: :app</span> <span class="k">do</span>
    <span class="n">run</span> <span class="s2">"ln -nfs </span><span class="si">#{</span><span class="n">shared_path</span><span class="si">}</span><span class="s2">/config/database.yml </span><span class="si">#{</span><span class="n">release_path</span><span class="si">}</span><span class="s2">/config/database.yml"</span>
  <span class="k">end</span>
  <span class="n">after</span> <span class="s2">"deploy:finalize_update"</span><span class="p">,</span> <span class="s2">"deploy:symlink_config"</span>

  <span class="n">desc</span> <span class="s2">"Make sure local git is in sync with remote."</span>
  <span class="n">task</span> <span class="ss">:check_revision</span><span class="p">,</span> <span class="ss">roles: :web</span> <span class="k">do</span>
    <span class="k">unless</span> <span class="sb">`git rev-parse HEAD`</span> <span class="o">==</span> <span class="sb">`git rev-parse origin/master`</span>
      <span class="nb">puts</span> <span class="s2">"WARNING: HEAD is not the same as origin/master"</span>
      <span class="nb">puts</span> <span class="s2">"Run `git push` to sync changes."</span>
      <span class="nb">exit</span>
    <span class="k">end</span>
  <span class="k">end</span>
  <span class="n">before</span> <span class="s2">"deploy"</span><span class="p">,</span> <span class="s2">"deploy:check_revision"</span>

<span class="k">end</span>
    </code></pre></figure>


config/nginx.conf

upstream unicorn {
  server unix:/tmp/unicorn.testapp.sock fail_timeout=0;
}

server {
  listen 80 default deferred;
  server_name testapp.dev.istickz.ru;
  root /var/www/testapp/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }


  try_files $uri/index.html $uri @unicorn;
  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
} ```    

config/unicorn.rb

    root = "/var/www/testapp/current"
    working_directory root
    pid "#{root}/tmp/pids/unicorn.pid"
    stderr_path "#{root}/log/unicorn.log"
    stdout_path "#{root}/log/unicorn.log"
    
    listen "/tmp/unicorn.testapp.sock"
    worker_processes 2
    timeout 30
    
    # Force the bundler gemfile environment variable to
    # reference the capistrano "current" symlink
    before_exec do |_|
      ENV["BUNDLE_GEMFILE"] = File.join(root, 'Gemfile')
    end

config/unicorn_init.sh

    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides:          unicorn
    # Required-Start:    $remote_fs $syslog
    # Required-Stop:     $remote_fs $syslog
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Manage unicorn server
    # Description:       Start, stop, restart unicorn server for a specific application.
    ### END INIT INFO
    set -e
    
    # Feel free to change any of the following variables for your app:
    TIMEOUT=${TIMEOUT-60}
    APP_ROOT=/var/www/testapp/current
    PID=$APP_ROOT/tmp/pids/unicorn.pid
    CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
    AS_USER=username
    set -u
    
    OLD_PIN="$PID.oldbin"
    
    sig () {
      test -s "$PID" && kill -$1 `cat $PID`
    }
    
    oldsig () {
      test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
    }
    
    run () {
      if [ "$(id -un)" = "$AS_USER" ]; then
        eval $1
      else
        su -c "$1" - $AS_USER
      fi
    }
    
    case "$1" in
    start)
      sig 0 && echo >&2 "Already running" && exit 0
      run "$CMD"
      ;;
    stop)
      sig QUIT && exit 0
      echo >&2 "Not running"
      ;;
    force-stop)
      sig TERM && exit 0
      echo >&2 "Not running"
      ;;
    restart|reload)
      sig HUP && echo reloaded OK && exit 0
      echo >&2 "Couldn't reload, starting '$CMD' instead"
      run "$CMD"
      ;;
    upgrade)
      if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
      then
        n=$TIMEOUT
        while test -s $OLD_PIN && test $n -ge 0
        do
          printf '.' && sleep 1 && n=$(( $n - 1 ))
        done
        echo
    
        if test $n -lt 0 && test -s $OLD_PIN
        then
          echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
          exit 1
        fi
        exit 0
      fi
      echo >&2 "Couldn't upgrade, starting '$CMD' instead"
      run "$CMD"
      ;;
    reopen-logs)
      sig USR1
      ;;
    *)
      echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
      exit 1
      ;;
    esac

Не забываем сделать файл исполняемым.

$ chmod +x config/unicorn_init.sh 

Запушим конфигурационные файлы в репозиторий:

$ git add .
$ git commit "Add configuration files"
$ git push origin master

Конфигурационные файлы готовы, пора приступать к заливке приложения, но прежде давайте заново авторизуемся на сервере и выставим права на папку /var/www/ для пользователя username:

$ sudo chown -R username:username /var/www
$ sudo chmod -R g+w /var/www

Теперь можно спокойно сказать Capistrano, чтобы подготовило необходимую структуру папок на сервере и закинуло конфигурационные файлы куда нужно.

$ cap deploy:setup

Редактировать мы будем только доступы к базе данных. Сначала создадим базу данных и пользователя для нее.

$ mysql -u root -p
mysql> CREATE DATABASE `testapp` CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> GRANT ALL PRIVILEGES ON testapp.* TO [email protected] IDENTIFIED BY 'password' WITH GRANT OPTION;

Теперь редактируем доступы к БД.

$ cd /var/www/testapp/shared/config
$ nano database.yml 

И вписываем пользователя и пароль.

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

$ cap deploy:cold

Готово! Теперь вы можете наблюдать за вашим приложением из браузера по ссылке http://yoursuperrailsapp.com

Осталось запускать unicorn сервер при каждом перезапуске дроплета.

$ sudo update-rc.d -f unicorn_testapp defaults

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

$ cap deploy

после чего все изменения уже будут на вашем сервере. На этом все. Исходный код приложения можно взять тут: [Github][7], а рабочий пример тут: http://testapp.dev.istickz.ru/

[2]: https://pbs.twimg.com/media/BdJoINTCcAA6ha0.jpg “” [3]: https://cloud.digitalocean.com/ssh_keys [4]: https://cloud.digitalocean.com/droplets/new [5]: http://i2.wp.com/istickz.ru/wp-content/uploads/2014/02/do-panel.png [6]: https://github.com/capistrano/capistrano [7]: https://github.com/istickz/testapp

comments powered by Disqus