[Chapter-4]EC2にRailsアプリの配置

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
今回はEC2にRailsアプリの配置をしていきます
自分の手順書としてのメモですので画像はありません。あしからず。

前提としてEC2のサーバー環境構築が終わっている状態とします。

##環境

```
nginx 1.12.2
PostgreSQL 11.5
node 12.22.1
yarn 1.22.5
rbenv 1.1.2
ruby 2.6.6
```

##GitHub連携に必要な公開鍵作成
最初にgitに関する設定ファイルを生成します。

`.gitconfig`ファイルを新たに作ります。

```:サーバー
$ cd ~
$ vim .gitconfig
```

以下を記述していきます。

```
[user]
  name = your_name #gitに登録した自分の名前
  email = hoge@gmail.com #git登録時の自分のメアド

[alias] #お好きに
  a = add
  b = branch
  ch = checkout
  st = status

[color] #色付け
  ui = true

# githubの場合
[url "github:"] #pull、pushのための設定
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:
# bitbucketの場合
[url "bitbucket:"]
    InsteadOf = https://ユーザ名@bitbucket.org/
    InsteadOf = git@bitbucket.org:
```

`shift`+`ZZ`で保存＆終了

次はアプリを配置するディレクトリを作成します。

```:サーバー構築
$ cd /
$ sudo mkdir var/www
$ sudo mkdir var/www/rails
$ sudo chown ユーザ名 var #ユーザに所有権を与える
$ cd var/
$ sudo chown -R ユーザ名 www　#このディレクトリ以下の所有権をユーザに与える
```
gitの接続に必要な鍵を格納するディレクトリに移動します。

```:サーバー
$ cd ~
$ chmod 700 .ssh #所有者に対して、読み取り、書き込み、実行の権限を与える
$ cd .ssh
```

```:サーバー
$ ssh-keygen -t rsa

以下のメッセージが表示されるので、「aws_git_rsa」と入力
Enter file in which to save the key ():aws_git_rsa

何もせずにエンター
Enter passphrase (empty for no passphrase):

何もせずにエンター
Enter same passphrase again
```

`ls`コマンドで**aws_key_rsa**と**aws_key_rsa.pub**が生成されたことを確認してください


configファイルを生成します。

```
$ vi config
-----------------------------
# githubの場合以下を追記
Host github github.com
  Hostname github.com
  User git
  IdentityFile ~/.ssh/aws_git_rsa
# bitbucketの場合以下を追記
Host bitbucket
  Hostname bitbucket.org
  User git
  IdentityFIle ~/.ssh/aws_git_rsa
-----------------------------

`Shift`+`ZZ`で保存＆終了
```

公開鍵の中身を表示する

```
$ cat aws_git_rsa.pub
ssh-rsa~~~
```
catで表示させた公開鍵をgithubにアクセスして登録します。

#公開鍵をGitHubにアップ
https://github.com/settings/ssh
上記のページでGitHubで公開鍵の設定が可能です。

GitHubのページへ遷移した後、「New SSH Key」ボタンを選択します。

以下の通り項目に記載
1 . Title：「aws_git_rsa.pub」 #公開鍵名
2 . Key：「ssh-rsa~~~」 #catで確認した公開鍵の中身
「Add SSH Key」ボタンをクリックする。

GitHub側の設定が終われば、ターミナルから接続が可能か確認してみます。

```:サーバー
ターミナルへ戻り設定ファイルの権限を変更(読み取りと書き込みの許可)
$ chmod 600 config

GitHubへの接続確認。途中の質問にはYesで。GitHubのユーザ名が出てくれば成功。
$ ssh -T git@github.com
```

##Githubからアプリをクローンする
いよいよアプリをクローンする時がきました。

```:サーバー
$ cd ~
$ cd /var/www/rails
$ git clone git@github.com:~~~~~~
```

git cloneの後に続くURLはGitHubの下記の手順で取得します。
1 . githubからデプロイしたいアプリのリモートレポジトリへ移動
2 . 「code」を選択
3 . 「SSH」を選択して、表示されているURLをコピーする

`ls`コマンドでアプリ名が記載されているディレクトリが存在すれば、クローンは成功です。
クローンしたアプリに移動し、必要なGemをインストールしましょう。

```:サーバー
$ cd アプリ名
$ bundle install
```

##アプリのシークレットの設定
クローンが成功したら、シークレットを生成します。
まずcredentials.yml.encの編集を行っていきます。

configディレクトリに格納されているファイルを確認しましょう

```:サーバー(/var/www/rails/アプリ名/)
$ ls config
```

これから、「credentials.yml.enc」の中身を編集していきます。

###1.マスターキーを作成
「credentials.yml.enc」を編集する為には
「master.key」が必要です。

ローカル環境の同ディレクトリには格納されていますが
サーバー環境の同ディレクトリには格納されていません。
「master.key」はGit管理しない様に設定されていて
本番サーバー上でプロジェクトのリポジトリをクローンしても、このファイルはついてこない様になっております。

そこで手動で「master.key」を生成します。
**ローカル環境**のクローン元のアプリディレクトリにて、以下の手順を実行してください。

```:ローカル(アプリ名/config)
$ vim master.key
```

表示された英数字をメモします。
次に**サーバー環境**で以下の手順を実行します。

```:サーバー(/var/www/rails/アプリ名/)
$ cd config
$ vim master.key

# ローカルのmaster.keyの値を入力
26286c42~~~
```
`Shift`+`ZZ`で保存＆終了

これで「credentials.yml.enc」を編集する準備ができました。

### 2.credentials.yml.encを編集

初めにローカル環境にてシークレットを生成します。
ローカル環境にて以下の手順を実行してください。

```:ローカル(アプリ名)
$ rake secret

jflaskfdk~~~~~~
```
表示されたシークレットキーをコピーします。
次はローカル環境で生成した、シークレットキーを「credential.yml.enc」に記載します。
サーバー環境でクローンした、アプリで以下の手順を実行します

```:サーバー環境(/var/www/rails/アプリ名/)
$ EDITOR=vim bin/rails credentials:edit

# aws:
#   access_key_id: 123
#   secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 01078f3faf42140621e86753aabcb~~~~ #シークレットキーをコピー
```

`Shift`+`ZZ`で保存＆終了
これでアプリのシークレットの設定は完了です


##Nginxの設定
Nginx（エンジンエックス）の設定ファイルを修正します。
以下の手順を実行します

```:サーバー(/var/www/rails/アプリ名/)
$ cd /etc/nginx/conf.d/
$ sudo vim アプリ名.conf

# log directory
error_log  /var/www/rails/アプリ名/log/nginx.error.log; #自分のアプリケーション名に変更
access_log /var/www/rails/アプリ名/log/nginx.access.log; #自分のアプリケーション名に変更

upstream unicorn_server {
    server unix:/var/www/rails/アプリ名/tmp/sockets/.unicorn.sock fail_timeout=0; #自分のアプリケーション名に変更
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name ~~~.~~~.~~~.~~~; #アプリのElastic IPに変更

    keepalive_timeout 5;

    # Location of our static files
    root /var/www/rails/アプリ名/public; #自分のアプリケーション名に変更

    location ~ ^/assets/ {
        root /var/www/rails/アプリ名/public; #自分のアプリケーション名に変更
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/rails/アプリ名/public; #自分のアプリケーション名に変更
    }
}
```
`Shift`+`ZZ`で保存＆終了

そして権限の変更をします。

```:サーバー(/var/www/rails/アプリ名/)
$ cd /var/lib
$ sudo chmod -R 775 nginx  #nginx以下のファイルに所有者、所有グループに全ての権限を付与、その他に読み取りと実行を許可
```

##Unicornの設定
Unicornはアプリケーションサーバーの一種です。
アプリ本体を格納するUnicornを設定していきましょう。

###1.Unicornのインストール
GemファイルにUnicornを追記

```:サーバー(/var/www/rails/アプリ名/)
vim Gemfile

----------------------------
#以下を追記
group :production, :staging do
    gem 'unicorn'
end
----------------------------
```

`Shift`+`ZZ`で保存＆終了

Unicornをインストール

```:サーバー(/var/www/rails/アプリ名/)
$ gem install bundler
$ bundle install
```

###2.Unicornの設定ファイルを作成

```:サーバー(/var/www/rails/アプリ名/)
$ vim config/unicorn.conf.rb

------------------------------------
#以下を記述：合計1箇所変更点があります
# set lets
  $worker  = 2
  $timeout = 30
  $app_dir = "/var/www/rails/アプリ名" #自分のアプリケーション名
  $listen  = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
  $pid     = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
  $std_log = File.expand_path 'log/unicorn.log', $app_dir
  # set config
  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid
  # loading booster
  preload_app true
  # before starting processes
  before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        Process.kill "QUIT", File.read(old_pid).to_i
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
  end
  # after finishing processes
  after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  end
------------------------------------
```

`Shift`+`ZZ`で保存＆終了
これでUnicornの設定も完了です

##PostgreSQLの設定
続いてはDBの設定をしていきます
(アプリケーションのDBがPostgreで作成されている前提で話を進めていきます。)
DBへアクセスする情報（ユーザー名やパスワード等）をdatabase.ymlへ直接記入するとセキュリティ的に問題があるので、環境変数を使用して情報を受け渡していきます。
今回は`dotenv-rails`を使用して変数管理を行っていきます。

###1.dotenv-railsの導入
Gemfileを編集する

```:サーバー(/var/www/rails/アプリ名/)
$ vim Gemfile
```
Gemfileに以下を追加します。

```
# 環境変数の管理をするもの
gem 'dotenv-rails'
```
`Shift`+`ZZ`で保存＆終了

インストール

```:サーバー(/var/www/rails/アプリ名/)
$ bundle install
```
シークレットキーを作成します。

```:サーバー(/var/www/rails/アプリ名/)
$ rake secret
```

表示されたシークレットキーはコピーします。

次にアプリケーションのルートディレクトリに.envファイルを作成し、
その中にシークレットキーの記述を記載してください。

```:サーバー(/var/www/rails/アプリ名/)
$ touch .env
$ vim .env

---------------------------
#シークレットキーにコピーしたキーを貼り付けます。
SECRET_KEY_BASE={シークレットキー}
```
`Shift`+`ZZ`で保存＆終了

ファイルの記述ができたら結果を確認します。

```:サーバー(/var/www/rails/アプリ名/)
$ source .env
$ echo $SECRET_KEY_BASE
```
シークレットキーの値が返ってきたら設定完了です。

###PostgreSQLの環境変数を設定
先ほどのenvファイルに、PostgreSQLの変数を設定していきます。
シークレットキーの下へ追記してください。
※ 他にも環境変数を入れる場合はここに入れてください！筆者の場合、S3関係の環境変数を使いました。

```:サーバー(/var/www/rails/アプリ名/)
$ vim .env

-----------------------
DB_NAME=travelour_production #作成したDB名
DB_USERNAME=taro #ロール名(ユーザ名のこと)
DB_PASSWORD=********* #パスワード
```
`Shift`+`ZZ`で保存＆終了
ここで入力したロール名とパスワードは使うので覚えておきましょう。
変数の値を確認しましょう

```:サーバー(/var/www/rails/アプリ名/)
$ source .env
$ echo $DB_NAME
$ echo $DB_USERNAME
$ echo $DB_PASSWORD
```

入力した情報が表示されれば完了です。

### 3.database.ymlを修正
環境変数を用いて、データベースにアクセスする設定を変更します。

```:サーバー環境(/var/www/rails/アプリ名/)
$ vim config/database.yml

#最下部の本番環境の記述のみ変更します
production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
```
`Shift`+`ZZ`で保存＆終了

###4.Postgresの起動
以下のコマンドでpostgresを起動します。

```:サーバー(/var/www/rails/アプリ名/)
$ sudo service postgres start
```
最初はデータベースにパスワードがかかっているため強制的にパスできる様にします。
まず'`pg_hba.conf`ファイルを編集します。

```
#pg_hba.confファイルを探す
$ sudo find / -print |grep pg_hba.conf
/var/lib/pgsql/data/pg_hba.conf

#見つけたファイルをvimで編集する
$ sudo vim /var/lib/pgsql/data/pg_hba.conf
------------------------------------
以下のように編集(peerをtrustに変更)

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust #ここをtrustにする
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
```
これでpostgresにログインできます。

postgersにログイン

```
$ psql -U postgres
```

ロールを作成 ※ロールの詳細は[こちら](https://qiita.com/Jackson123/items/e1e62db65eeb3602ae92)
`taro`と`11111111`はロール名とパスワードです。

```
postgres=# CREATE ROLE taro WITH PASSWORD '11111111';
```
`CREATE ROLE`と表示されれば成功です。
`SELECT ROLNAME FROM pg_roles;`でちゃんと表示されているか確認してみましょう

```
postgres=# SELECT ROLNAME FROM pg_roles;
 rolname
ーーーーーーーー
 postgres
 taro
(2 行)
```

`ALTER ROLE`コマンドでログインとデータベース作成、権限を与える

```
postgres=# ALTER ROLE taro LOGIN;

postgres=# ALTER ROLE taro WITH CREATEDB;
```
`exit`でpostgresからログアウトする

データベース作成とマイグレーションを実行

```:サーバー
$ rake db:create RAILS_ENV=production
$ rake db:migrate RAILS_ENV=production
```

本番環境をプリコンパイルする

```:サーバー
$ bundle exec rake assets:precompile RAILS_ENV=production
```
Nginxを起動

```:サーバー
$ start nginx.service
```
Unicornを起動

```:サーバー
$ bundle exec unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production
```
Uniconの起動を確認(プロセスのリストが3行程表示されればOK)

```:サーバー
$ ps -ef | grep unicorn | grep -v grep
taro    24411     1 13 19:46 ?        00:00:02 unicorn_rails master -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
taro    24419 24411  0 19:46 ?        00:00:00 unicorn_rails worker[0] -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
taro    24420 24411  0 19:46 ?        00:00:00 unicorn_rails worker[1] -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
```
Nginxを再起動します。

```:サーバー
$sudo nginx -s reload
```

ブラウザにIPを入力してアクセスします。※IPアドレスはElastic IP

```
http://IPアドレス/
```

Railsが動作すれば成功です。