はじめに
表題の通りですがAWSにて環境構築から独自ドメイン取得までを記載しております。
rails5.2以降でのデプロイが難航し環境構築から独自ドメイン取得まで一貫した記事が無く、人柱となりて共有できればと思い記事として残すことにしました。
rails5.2以降ではsecrets.ymlがcredentials.yml.encに変更になり、呼び出し方が異なるのでその部分が躓くかと存じます。また、ドメイン・SSL化はなかなか教材には無かったのでご参考になれば幸いです。不手際がございましたら、コメントにいただけると有り難いです。
できるだけコピペでいきたいですね。では参りましょう!
前提条件
- githubにリポジトリが登録できている
- そのリポジトリに rails new したもの(rails5.2以降)が登録できている
- databaseはmysqlである
- AWSでアカウントが登録できている
- 寛大な心を持っている
流れ
- AWS内の環境構築
- unicornの導入
- nginxの導入
- capistranoの導入
- お名前.comでドメインを購入し、AWSと紐付け
- 無料SSL化(Let's Encrypt)
AWS内の環境構築
AWSのEC2というサービスを使って、全世界に作成したサイトを公開するサーバを作成します。いくつかの設定をし、作成したサーバにログインして操作できるようにします。EC2で作成したサーバは、結局はターミナルを介して遠隔操作できるパソコンです。慣れましょう!(投げやり感)
- AWSアカウントのリージョン設定
リージョンとは、AWSの物理的なサーバの場所を指定するものです。リージョンは世界各地に10箇所以上存在し、そのうちの一つは東京にあります。
まずは【こちら】からAWSアカウントにログインします。次に日本にお住まいの方は「東京」を選択してください。
- EC2インスタンスの作成
「仮想マシン」のことをAWSでは「EC2インスタンス」と呼んでいます。
「EC2」を選択しましょう。
以下の画像のように「インスタンスの作成」をクリックしましょう。
以下の画像のように「 Amazon Linux AMI 」を選択してください。
EC2インスタンスのタイプを選択します。EC2ではさまざまなインスタンスタイプが用意されており、CPUやメモリなどのスペックを柔軟に指定することができます。
今回は、無料枠で利用できる「t2.micro」を選択しましょう。
「キーペア」をダウンロードすることが出来ます。こちらはインスタンスにSSHでログインする際に必要となる「秘密鍵」です。これがないとEC2インスタンスにログインできないので、必ずダウンロードしてパソコンに保存しておきましょう。
※スペースを含まない名前の秘密鍵を作成するようにしましょう!
キーペアのダウンロードが完了すると、クリック出来ない状態になっていた「インスタンスの作成」が、クリックできるように変更されます。そちらをクリックして、EC2インスタンスを作成しましょう。
その後、インスタンス一覧画面に戻り、作成した「インスタンスID」をコピーしてメモしておきましょう。
- Elastic IPの作成と紐付け
Elastic IPとは、AWSから割り振られた固定のパブリックIPアドレスのことです。
Elastic IPを取得するために、以下の画像の手順に従って作業をしていきましょう。
上の画像のようにインスタンスを選択すると、その下にあるプライベートIPアドレスが自動で選択されます。
再びインスタンス一覧画面に戻り、作成したインスタンスの「パブリック IP」と「Elastic IP」が同じものに設定されていることを確認しましょう。
- ポート解放1
立ち上げたばかりのEC2インスタンスはSSHでアクセスすることはできますが、HTTPなどの他の接続は一切つながらないようになっています。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
「ルールの追加」をクリックします。
タイプを「HTTP」、プロトコルを「TCP」、ポート範囲を「80」、送信元を「カスタム / 0.0.0.0/0, ::/0」に設定します。「0.0.0.0」や「::/0」は「全てのアクセスを許可する」という意味です。
- EC2インスタンスへのログイン
EC2インスタンスを作成すると、ec2-userというユーザーと対応するSSH秘密鍵が生成されました。
ターミナルで以下のコマンドを実行しましょう。
$ cd ~
$ mkdir ~/.ssh
# .sshというディレクトリを作成
# File existsとエラーが表示されたとしても、.sshディレクトリは存在しているということなので、そのまま進みましょう。
$ mv Downloads/ダウンロードした鍵の名前.pem .ssh/
# mvコマンドで、ダウンロードしたpemファイルを、ダウンロードディレクトリから、.sshディレクトリに移動します。
$ cd .ssh/
$ ls
# pemファイルが存在するか確認しましょう
$ chmod 600 ダウンロードした鍵の名前.pem
$ ssh -i ダウンロードした鍵の名前.pem ec2-user@作成したEC2インスタンスと紐付けたElastic IP
#(例えばElastic IPが123.456.789であれば、shh -i ダウンロードした鍵の名前.pem ec2-user@123.456.789 というコマンドになります)
#(ダウンロードした鍵を用いて、ec2-userとしてログイン)
Elastic IP は各自のAWSアカウントから確認してください。
以下の様なメッセージが表示されることがありますが、「yes」と入力して下さい。
$ ssh -i aws_key.pem ec2-user@52.68.~~~~~~
The authenticity of host '52.68.~~~~~~ (52.68.~~~~~~)' can't be established.
RSA key fingerprint is eb:7a:bd:e6:aa:da:~~~~~~~~~~~~~~~~~~~~~~~~.
Are you sure you want to continue connecting (yes/no)?
ターミナルのコマンド待ちの際の左側の表示が、以下の画像のように
[ec2-user| ...
以上で、AWSの設定とEC2インスタンスの生成が完了でございます。
- 必要なツールのインストール
ターミナルで以下のコマンドを実行しパッケージをアップデートしましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y update
次に、その他環境構築に必要なパッケージを諸々インストールします。
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
ちなみに-y はyumコマンドのオプションで全ての問いにYesで自動的に答えるという意味だぞ❤️
- Node.jsをインストール
サーバーサイドで動くJavaScriptのパッケージです。今後のデプロイに向けた作業の中で、CSSや画像を圧縮する際に活用されます。ターミナルでNode.jsをインストールしましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nodejs
- rbenvとruby-buildをインストール
ターミナルでrbenvとruby-buildをインストールしましょう。
#rbenvのインストール
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
#パスを通す
[ec2-user@ip-172-31-25-189 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
#rbenvを呼び出すための記述
[ec2-user@ip-172-31-25-189 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
#.bash_profileの読み込み
[ec2-user@ip-172-31-25-189 ~]$ source .bash_profile
#ruby-buildのインストール
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
#rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
- Rubyをインストール
自身のアプリケーションで使っているRubyのバージョンによって適宜変更してください。
ここでは、2.5.1をインストールしていきます。
[ec2-user@ip-172-31-25-189 ~]$ rbenv install 2.5.1
[ec2-user@ip-172-31-25-189 ~]$ rbenv global 2.5.1
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash #rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ ruby -v # バージョンを確認
- MySQLをインストール
Amazon Linuxを利用している場合、MySQLは yum コマンドからインストールすることができます。
以下のコマンドを実行してください。
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install mysql56-server mysql56-devel mysql56
これは、MySQLのバージョン5.6をインストールすることを意味します。
- MySQLを起動しよう
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld start
mysql ではなく mysqld であることに注意しましょう。「d」はLinuxの用語で「サーバ」を意味する「デーモン(daemon)」の頭文字です。
起動できたか確認するために、以下のコマンドを打ってみましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld status
mysqld (pid 15692) is running...
「running」と表示されれば、MySQLの起動は成功です。
- MySQLのrootパスワードの設定
以下のコマンドでパスワードを設定しましょう。'設定したいパスワード'の部分については、例えばpassword0000という文字列を設定するとしたら、 'password0000'と記載しましょう。
※0から始まるpasswordは読み込んでくれないケースが多いので、避けましょう!
[ec2-user@ip-172-31-25-189 ~]$ sudo /usr/libexec/mysql56/mysqladmin -u root password 'ここを設定したいパスワードに変更してからコマンドを実行してください'
このパスワードは、後ほどRailsからアクセスする時にも利用するので記憶しておいてください。
この時、Warning: Using a password on the command line interface can be insecure.
と警告がでることがありますが、ここでは無視していただいて問題ありません。
設定したパスワードが使えるか確認してみましょう。以下のコマンドを入力してください。
[ec2-user@ip-172-31-25-189 ~]$ mysql -u root -p
Enter password: とパスワードを入力するように表示されるので、先程設定したパスワードを入力して、Enterしてください。以下のように表示されれば、MySQLの設定は終了です。
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.6.33 MySQL Community Server (GPL)
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
以上で、各ツールのインストールが完了でございます。
- EC2のサーバにGithubのコードをクローン
現状、EC2サーバにアプリケーションのコードをクローンしようとしてもpermission deniedとエラーが出てしまいます。
これは、Githubから見てこのEC2インスタンスが何者かわからないためです。
以下のコマンド入力して、EC2サーバのSSH鍵ペアを作成しましょう。
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
3a:8c:1d:d1:a9:22:c7:6e:6b:43:22:31:0f:ca:63:fa ec2-user@ip-172-31-23-189
The key's randomart image is:
+--[ RSA 4096]----+
| + |
| . . = |
| = . o . |
| * o . o |
|= * S |
|.* + . |
| * + |
| .E+ . |
| .o |
+-----------------+
次に、以下のコマンドで生成されたSSH公開鍵を表示し、値をコピーします。
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2E......
そして、catで表示させた公開鍵を、Githubにアクセスして登録していきます。
まず、以下のURLにアクセスしてください。
https://github.com/settings/keys
Githubに鍵を登録できたら、SSH接続できるか以下のコマンドで確認してみましょう。
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.
途中でこのまま続けるかどうかYes/Noで聞かれることがありますが、Yesで進んでください。
Permission denied (publickey).
と表示された場合は、SSH鍵の設定が間違っているので、作業を確認してください。
unicornの導入
unicornは rails s の代わりを担ってくれるアプリケーションサーバです。(アバウトすぎw)
- Unicornをインストール
次のように ローカルでGemfile を編集しましょう。
group :production do
gem 'unicorn', '5.4.1'
end
ローカルのrails newしたディレクトリでbundle installコマンドを実行してください。
$ bundle install
config/unicorn.rbを作成し、内容を以下のように編集して保存しましょう。
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)
#アプリケーションサーバの性能を決定する
worker_processes 1
#アプリケーションの設置されているディレクトリを指定
working_directory app_path
#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"
#ポート番号を指定
listen 3000
#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"
#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"
#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60
#以下は応用的な設定なので説明は割愛
preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true
check_client_connection false
run_once = true
before_fork do |server, worker|
defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
if run_once
run_once = false # prevent from firing again
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exist?(old_pid) && server.pid != old_pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH => e
logger.error e
end
end
end
after_fork do |_server, _worker|
defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
- デプロイ時のエラー対策
Uglifierというgemがあり、これはJavaScriptを軽量化するためのものです。しかし、ChatSpaceのJavaScriptで使用しているテンプレートリテラル記法(`)に対応していません。そのため、デプロイ時にエラーの原因となります。
デプロイ時にエラーの原因となる記述の対策として、下記のフォルダを編集しましょう。
config.assets.js_compressor = :uglifier
# config.assets.js_compressor = :uglifier
- 変更修正をリモートリポジトリに反映
ここまで、ローカルのフォルダ内で変更修正を行ったので、GitHub Desktopからコミットしてプッシュしましょう。この時必ず、masterブランチで行うようにしてください。もし、別ブランチでコミット&プッシュした場合は、リモートリポジトリでプルリクエストを作成し、ブランチをmasterへマージしてください。
- Githubからコードをクローン
続いて、Unicornの設定を済ませたコードをEC2インスタンスにクローンしましょう。
まず、以下のコマンドを入力して、ディレクトリを作成します。今回は、ここで作成したディレクトリにアプリケーションを設置することにします。
#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/
#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-172-31-23-189 ~]$ sudo chown ec2-user /var/www/
取得した「リポジトリURL」を使って、コードをクローンします。
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone https://github.com/<ユーザー名>/<リポジトリ名>.git
- Swap領域を用意
コンピュータが処理を行う際、メモリと呼ばれる場所に処理内容が一時的に記録されます。メモリは容量が決まっており、容量を超えてしまうとエラーで処理が止まってしまいます。Swap領域は、メモリが使い切られそうになった時にメモリの容量を一時的に増やすために準備されるファイルです。
まずは、ホームディレクトリに移動します。
#ホームディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd
続いて、以下の順番でコマンドを実行します。
#処理に時間がかかる可能性があるコマンドです
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
# しばらく待って、以下のように表示されれば成功
512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 7.35077 秒、 73.0 MB/秒
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1
# 以下のように表示されれば成功
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1 none swap sw 0 0" >> /etc/fstab'
※最後のコードは見づらくなっていますが、「/swapfile1 none」より右に続きがありますのでご注意ください。
これで、Swap領域を確保することができました。
- クローンしたディレクトリに移動し、 rbenvでインストールされたRubyが使われているかチェック
[ec2-user@ip-172-31-23-189 www]$ cd /var/www/<リポジトリ名>
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ruby -v
ruby 2.5.1p112 (2016-04-26 revision 54768) [x86_64-linux]
**ruby 2.5.1 ...**となっていれば成功です。そうでない場合は、もともと用意されているRubyが利用されているので、Rubyのインストールが成功しているか確認してください。
- bundlerをインストール
まず今まで開発環境(ローカル)で開発してきたアプリにおいて、どのバージョンのbundlerが使われていたのか確認します。
#アプリのディレクトリで以下を実行
$ bundler -v
Bundler version 2.0.1
# 開発環境によってバージョンは異なります。
開発環境で仕様しているbundlerのバージョンがわかったので、同じバージョンのものをEC2サーバ側にも導入します。上記の場合では、bundler 2.0.1のバージョンを導入して bundle install を実行します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ gem install bundler -v 2.0.1
# ローカルで確認したbundlerのバージョンを導入する
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle install
# 上記コマンドは、数分以上かかる場合もあります。
- 環境変数の設定
データベースのパスワードなどセキュリティのためにGithubにアップロードすることができない情報は、環境変数というものを利用して設定します。
- secret_key_base
secret_key_baseとは、Cookieの暗号化に用いられる文字列です。Railsアプリケーションを動作させる際は必ず用意する必要があります。また、外部に漏らしてはいけない値であるため、こちらも環境変数から参照します。
以下のコマンドを打つことで生成できます。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rake secret
69619d9a75b78f2e1c87ec5e07541b42f23efeb6a54e97da3723de06fe74af29d5718adff77d2b04b2805d3a1e143fa61baacfbf4ca2c6fcc608cff8d5a28e8d
この長い英数の羅列は、この後利用するのでコピーしておきましょう。
- 実際にEC2インスタンスに環境変数を設定
環境変数は /etc/environment というファイルに保存することで、サーバ全体に適用されます。環境変数の書き込みはvimコマンドを使用して行います。
[ec2-user@ip-172-31-23-189 ~]$ sudo vim /etc/environment
iと打ち込んで入力モードに切り替えた後、下記の記述を打ち込みます。=の前後にスペースは入れません。
#先程設定したMySQLのrootユーザーのパスワードを入力
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'
入力ができたら、escキーを押した後、:wqで保存しましょう。
- 設定した環境変数を反映させるために、一度本番環境をログアウト
[ec2-user@ip-172-31-23-189 ~]$ exit
logout
Connection to 52.xx.xx.xx closed.
- もう一度本番環境へログイン
$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
(ダウンロードした鍵を用いて、ec2-userとしてログイン)
- 設定した環境変数が本当に適用されているか確認
[ec2-user@ip-172-31-23-189 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'
[ec2-user@ip-172-31-23-189 ~]$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
- ポート解放2
先程、 config/unicorn.rb に listen 3000を設定しました。そのため、WEBサーバとして利用するEC2インスタンスは事前にHTTPがつながるように「ポート」を開放する必要があります。
「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
「ルールの追加」をクリックします。
タイプを「カスタムTCPルール」、プロトコルを「TCP」、ポート範囲を「3000」、送信元を「カスタム」「0.0.0.0/0」に設定します。
以上で、ポートの開放が完了です。
この作業が終わっていないと、起動したRailsにアクセスできないので注意してください。
- Railsを起動する
いよいよRailsの起動です。
以下のコマンドを実行し、ユニコーンを起動
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/[リポジトリ名]
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
このコマンドを実行すると、以下のようにすぐにコマンドが終了してしまいます。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
master failed to start, check stderr log for details
なので、Unicornのエラーログを確認しましょう。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/unicorn.stderr.log
I, [2016-12-21T04:01:19.135154 #18813] INFO -- : Refreshing Gem list
I, [2016-12-21T04:01:20.732521 #18813] INFO -- : listening on addr=0.0.0.0:3000 fd=10
E, [2016-12-21T04:01:20.734067 #18813] ERROR -- : Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/mysql2_adapter.rb:29:in `rescue in mysql2_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/mysql2_adapter.rb:12:in `mysql2_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:721:in `new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:765:in `checkout_new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:744:in `try_to_checkout_new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:705:in `acquire_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:501:in `checkout'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:364:in `connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:875:in `retrieve_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:128:in `retrieve_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:91:in `connection'
config/unicorn.rb:36:in `block in reload'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:502:in `spawn_missing_workers'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:132:in `start'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/unicorn-5.1.0/bin/unicorn_rails:209:in `<top (required)>'
/home/ec2-user/.rbenv/versions/2.5.1/bin/unicorn_rails:23:in `load'
/home/ec2-user/.rbenv/versions/2.5.1/bin/unicorn_rails:23:in `<main>'
このERRORという行を見てみると、これは本番環境でインストールするmysqlの設定がローカルとは異なるため、mysqlへ接続できなくなっている状態です。
database.ymlの本番環境の設定を編集
production:
<<: *default
database: <リポジトリ名>_production(それぞれのアプリケーション名によって異なっています。)
username: root
password: <%= ENV['DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock
ローカルでの編集をコミットして、GitHubにプッシュ。
サーバ上のアプリケーションにも反映させたいので、以下のようにコマンドを実行してください。
[ec2-user@ip-172-31-23-189 <リポジトリ名>] git pull origin master
データベースを作成しマイグレーションを実行し直し。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production
もしここでMysql2::Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'というエラーが起こった場合、mysqlが起動していない可能性があります。sudo service mysqld startというコマンドをターミナルから打ち込み、mysqlの起動を試してみましょう。
再度Railsを起動。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
ブラウザで http://<サーバに紐付けたElastic IP>:3000/ にアクセスしてみましょう。
ブラウザにCSSの反映されていない(ビューが崩れている)画面が表示されていれば成功です。
アセットファイルをコンパイル
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production
コンパイルが成功したら反映を確認するため、Railsを再起動したいので今動いているUnicornをストップ&スタートします。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...
すると、以下のようにプロセスが表示されるはずです。
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn
killコマンドを入力してUnicornのプロセスを停止
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID>
...
再度、プロセスを表示させ終了できていることを確認しましょう。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
...
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn
下記の2行が表示が消えていない場合はプロセスが終了できていないことになります。
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
そのような場合は、プロセスを強制終了しましょう。オプション-9をkillコマンドにつけると強制終了を実行できます。通常のkillコマンドで削除できない場合はこちらを使用しましょう。
[ec2-user@ip-172-31-25-189 ~]$ kill -9 [プロセスID]
#プロセスIDはpsコマンドで検索した結果の数字に置き換えてください。上記であれば17877です。
unicornを起動
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
...
もう一度、ブラウザで http://<Elastic IP>:3000/ にアクセスしてみましょう。今度はレイアウト崩れも無くサイトが正常に表示されていることでしょう。
nginxの導入
Nginx(エンジン・エックス)とは、Webサーバの一種です。
- Nginxをインストール
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nginx
- Nginxの設定ファイルを編集
vimコマンドを使ってターミナル上で編集していきます。
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
# Unicornと連携させるための設定。アプリケーション名を自身のアプリ名に書き換えることに注意。今回であればおそらくchat-space
server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}
# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
# このプログラムが接続を受け付けるポート番号
listen 80;
# 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
server_name <Elastic IP>;
# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
client_max_body_size 2g;
# 接続が来た際のrootディレクトリ
root /var/www/<アプリケーション名>/public;
# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
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://app_server;
}
error_page 500 502 503 504 /500.html;
}
以下の3点は書き換えが必須です。
3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
11行目の<Elastic IP>となっている箇所も同様に、ご自身のものに変更してください。
14行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
※この場合<>は記入不要なもの/表示されないものとして捉えてください。説明のための日本語文字列を明示するために<>で囲んでいます。
- nginxの権限を変更
設定が完了したら、POSTメソッドでもエラーが出ないようにするために、下記のコマンドも実行してください。
[ec2-user@ip-172-31-25-189 ~]$ cd /var/lib
[ec2-user@ip-172-31-25-189 lib]$ sudo chmod -R 775 nginx
これで、Nginxの設定が完了しました。
- Nginxを再起動して設定ファイルを再読み込み
[ec2-user@ip-172-31-25-189 lib]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
- ローカルでunicorn.rbを修正
次にNginxを介した処理を行うためにunicornの設定を修正します。
listen 3000
↓以下のように修正
listen "#{app_path}/tmp/sockets/unicorn.sock"
ローカルで編集したファイルをリモートへpush
- ローカルの変更点を本番環境へ反映
# まず、chat-spaceのディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd /var/www/chat-space
[ec2-user@ip-172-31-23-189 <レポジトリ名>]$ git pull origin master
- Unicornを再起動
まず、プロセスの番号を確認します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn
続いて、プロセスをkillします。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID(上のコードでは17877)>
...
Unicornを起動します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
...
- ブラウザからElastic IPでアクセス
ブラウザからElastic IPでアクセスすると、アプリケーションにアクセスできます(:3000をつける必要はありません)。なお、この時もunicornが起動している必要があります。
capistranoの導入
capistranoは、自動デプロイツールと呼ばれるものの一種です。自動デプロイツールを利用することによって、デプロイ時に必要なコマンド操作が1回で済むようになります。
- capistranoを利用するためのGemをインストール
group :development, :test do
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano3-unicorn'
end
続いて、Gemfileを読み込みましょう。
bundle install
gemを読み込めたら、下記のコマンドを打ちます。
bundle exec cap install
すると、下記のようにファイルが生成されます。
アプリケーション名
📂capfile
🗂config
📂deploy
💎production.rb
💎staging.rb
💎deploy.rb
🗂lib
🗂capistrano
🗂tasks
- Capfileを編集
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
- production.rbを下記のように編集
server '<用意したElastic IP>', user: 'ec2-user', roles: %w{app db web}
- 下記の指示に従い、deploy.rbを編集
deploy.rbの記述をすべて削除し、以下のコードを貼り付けます。
# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'
# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'
# どのリポジトリからアプリをpullするかを指定する
set :repo_url, 'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'
# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :rbenv_type, :user
set :rbenv_ruby, 2.5.1 #<このアプリで使用しているrubyのバージョン>
# credentials.yml.encではmasterkeyにする
set :linked_files, %w{config/master.key}
# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
keys: ['<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス(例:~/.ssh/key_pem.pem)>']
# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5
# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
task :restart do
invoke 'unicorn:stop'
invoke 'unicorn:start'
end
desc 'upload master.key'
task :upload do
on roles(:app) do |host|
if test "[ ! -d #{shared_path}/config ]"
execute "mkdir -p #{shared_path}/config"
end
upload!('config/master.key', "#{shared_path}/config/master.key")
end
end
before :starting, 'deploy:upload'
after :finishing, 'deploy:cleanup'
end
以下の5点は書き換えが必須です。
- 3行目のはご自身のバージョンを記述しましょう。
- 6行目の<自身のアプリケーション名>はご自身のものを記述しましょう。
- 9行目の/<レポジトリ名>も同様に、ご自身のもの記述してください。
- 14行目の<このアプリで使用しているrubyのバージョン>はご自身のものを確認して記述してください。
- 21行目の<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス>も同様に、ご自身のもの記述してください。
- 以下の指示にしたがって、unicorn.rbの記述を編集
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../../', __FILE__)
#アプリケーションサーバの性能を決定する
worker_processes 1
#アプリケーションの設置されているディレクトリを指定
working_directory "#{app_path}/current"
# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60
#以下は応用的な設定なので説明は割愛
preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true
check_client_connection false
run_once = true
before_fork do |server, worker|
defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
if run_once
run_once = false # prevent from firing again
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exist?(old_pid) && server.pid != old_pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH => e
logger.error e
end
end
end
after_fork do |_server, _worker|
defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
- 本番環境でのnginxの設定ファイルも変更
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
以下のように変更しましょう
upstream app_server {
# sharedの中を参照するよう変更
server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name <Elastic IPを記入>;
# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
client_max_body_size 2g;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/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://app_server;
}
error_page 500 502 503 504 /500.html;
}
もう一度記述すべき箇所が記述できているか確認しましょう。
- 3行目の<アプリケーション名> となっている箇所は、ご自身のものに変更してください。
- 11行目の<アプリケーション名>となっている箇所も同様に、ご自身のものに変更してください。
- 18行目の<アプリケーション名>となっている箇所も同様に、ご自身のものに変更してください。
Nginxの設定を変更したら、忘れずに再読込・再起動をしましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx reload
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
- MySQLの起動を確認
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld restart
- unicornのプロセスをkill
自動デプロイを実行する前にunicornのコマンドをkillしておきましょう。
まず、プロセスを確認します。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn
続いて、プロセスをkillします。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのPID(上記では17877)>
...
- ローカルのcredentials.yml.encを編集
ここで注意したいのが、本番環境のcredentials.yml.encを編集すると、master.keyが自動生成されてしまい、ローカル環境のmester.keyが一致しなくなり、起動できなくなるので注意が必要です。
もし、本番環境のcredentials.yml.encを編集してしまった場合は、一度master.keyとcredentials.yml.encをコマンドで消去し、ローカルのcredentials.yml.encをpullしましょう。
下記コマンドで暗号化されていない、credentials.yml.encを開くことができ、編集することができます。
$ EDITOR=vim bin/rails credentials:edit
# S3使用時
# aws:
# access_key_id: 123
# secret_access_key: 123
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 先程コピーしたsecret_key_base
secret_key_baseは上記で作成したものを貼り付けましょう。
もし、忘れてしまった場合、本番環境での確認方法は下記の通りです。
[ec2-user@ip-172-31-23-189 ~]$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='secret_key_base'
- 本番環境のshared/configにmaster.keyを作成
このままデプロイしても以下のようなエラーが出てしまいます。
ERROR linked file /var/www/techlog/shared/config/master.key does not exist on <Elastic IP>
エラー通り、本番環境のshared/configにmaster.keyを作ります。
[ec2-user@ip-172-31-23-189 ~]$ touch /var/www/アプリケーション名/shared/config/master.key
作成したmaster.keyを編集します。
[ec2-user@ip-172-31-23-189 ~]$ vim /var/www/アプリケーション名/shared/config/master.key
ローカルのmaster.keyの内容をコピーし、本番環境のmaster.keyにコピーします。
以上で編集作業完了です。
- 最後に魔法の一文
ローカルで下記のコマンドを入力すると、自動デプロイを実行できます。
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy
上記コマンドを実行し、以下の画像のようにエラーが表示されずに完了したら自動デプロイは完了です。
もし、途中でエラーが出て止まってしまった場合は、以下を試します。
- そのままもう一度同じコマンドを実行してみる
特に、bundle installのタスクの際に、初めて自動デプロイを実行する場合は、メモリ不足で落ちることがあります - 記述ミスが無いか
特に、本カリキュラムにおいて、修正したファイルに注目して確認しましょう - 手順を飛ばしていないか
bundle installなどのコマンド実行を忘れていないか確認しましょう
- ブラウザからElastic IPでアクセス
ブラウザからElastic IPでアクセスすると、アプリケーションにアクセスできます(:3000をつける必要はありません)。正しく動いていることを確認しましょう。
確認できればデプロイは一旦完了です。長時間お疲れ様でした!
お名前.comでドメインを購入し、AWSと紐付け
大まかな流れです。
- お名前.comでドメインを購入
- route53にDNSの設定と、ElasticIPの登録
- お名前ドットコムにroute53の情報を登録
では参りましょう!
- お名前.comでドメインを購入
お名前.comでアカウント登録と取得したいドメインを購入しましょう。
年単位での契約になります。
- route53とは
AWSのDNSサービスで、AWS上の各サービスを独自ドメインで利用する上で便利な機能が用意されていて親和性が高いサービスになっています。
- route53の設定!
route53にログイン
awsマネジメントコンソールのサービスから、Route 53を開きます。
DNS管理のところにある「今すぐ始める」ボタンを押していきます。
「ホストゾーンを作成」ボタンを押して、どのドメインに関するホストゾーンを作成するかを設定していきます。
「ドメイン名」のところには、お名前.comで取得したドメインを入力します。
ホストゾーンを作成すると、NSレコードにネームサーバーが4つ割り当てられています。
このネームサーバーの情報はお名前.com側の設定で入力するので内容をメモしておきます。
- 作成したホストゾーンにEC2の固定IPアドレスを割り当てる
「レコードセットの作成」ボタンを押して、「名前」に対象のドメイン、値にEC2で割り当てられた固定IPアドレスを入力し「作成」ボタンを押せば完了です。
- お名前.comの設定でRoute 53に向けるネームサーバーの設定を行う
ドメインNaviでAWSで利用するドメインの設定を開き、ネームサーバーの変更から「他のネームサーバーを利用」を選択します。
ネームサーバー情報の入力欄に、Route 53のホストゾーンのNSレコードに表示されていたネームサーバーを4つとも入力し登録できれば設定は完了です。
これでお名前.comで取得したドメインにアクセスした際に、AWSのRoute 53で受けることができるようになりました。
- ドメインの動作確認
最後に動作確認をします。
本番環境で下記のコードを入力しましょう。
グローバル IP アドレスが返ってくれば名前解決が出来ています。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ nslookup xxxxxxxxxx.com
Server: 10.0.0.2
Address: 10.0.0.2#53
Non-authoritative answer:
Name: xxxxxxxx.com
Address: 54.178.156.248
Name: xxxxxxxx.com
Address: 52.197.167.212
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$
ブラウザを開き、ドメイン名を入力し、インターネット経由でアクセスできるか確認します。
Welcome to nginx on the Amazon Linux AMI!と表示されていれば成功です。
- nginxの設定ファイルを編集
これではまだ、表示することができないので、nginxの設定ファイルを編集しましょう。
vimコマンドを使ってターミナル上で編集していきます。
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
# sharedの中を参照するよう変更
server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name <Elastic IPを記入> <ドメイン名>;
# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
client_max_body_size 2g;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/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://app_server;
}
error_page 500 502 503 504 /500.html;
}
注目すべきは8行目です。
server_name <Elastic IPを記入> <ドメイン名>;
ドメイン名が追加されていますね!
xxx.comの場合はserver_name xxx.com
としましょう。escキーを入力後に:wqで上書き保存を忘れずに!
Elastic IPとドメイン名の間は必ず半角スペースを入力しましょう。
Nginxの設定を変更したら、忘れずに再読込・再起動をしましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
ブラウザをリロードし、ドメインで表示できていれば成功です。
できない場合、ブラウザのキャッシュを消去した後、ブラウザをリロードすれば表示できるかと存じます。
無料SSL化(Let's Encrypt)
無料のSSLサーバー証明書(以下、SSL証明書)であるLet’s Encryptは、米国の非営利団体であるISRG(Internet Security Research Group)により運営されています。全てのWebサイトを暗号化することを目指したプロジェクトであり、2019年6月現在では世界で1億枚以上の有効な証明書を発行しています。
非営利団体ということで財務基盤に不安を覚える方もいるかもしれませんが、現在ではFacebookやシスコシステムズ、Akamai Technologies、Verizonといった数多くの大手企業に支えられています。
Let’s Encryptでは、90日間有効なDV(Domain Validation)SSL証明書を2つの認証方式(ドメイン認証、DNS認証)で提供しています。SSL証明書は無料で提供されていますが、暗号強度などは一般的に販売されているSSL証明書と違いはありません。
ではレッツゴー!
- certbotをクローン
[ec2-user@ip-172-31-25-189 ~]$ cd /usr/local
[ec2-user@ip-172-31-25-189 local]$ sudo git clone https://github.com/certbot/certbot
[ec2-user@ip-172-31-25-189 local]$ cd certbot
- 証明書の作成を申請
申請するにあたって、Let's Encryptが認証するためのディレクトリを作成します。
(他の記事では/var/www/htmlなどとしている場合が多いですが、Amazon Linuxではデフォルトでそのようなディレクトリはないので、新たに作成します。)
# ディレクトリ名は自由ですが、今回は letsencrypt-webroot とします。
[ec2-user@ip-172-31-25-189 ~]$ sudo mkdir /var/www/letsencrypt-webroot
さらに、nginxを書き換えます。
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
# sharedの中を参照するよう変更
server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name <Elastic IPを記入> <ドメイン名>;
# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
client_max_body_size 2g;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/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://app_server;
}
# 以下を追加(^~は前方一致です)
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt-webroot;
}
error_page 500 502 503 504 /500.html;
}
その後、nginxを再起動します。
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
次に、以下のコマンドで認証可能かどうかを確認します。
(認証申請が1時間に5回Failすると、一定時間申請できなくなります(Rate Limits - Let's Encrypt - Free SSL/TLS Certificates)。そのため、先に認証可能かどうかを確認します。)
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ /usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot --dry-run
以下が出たら認証可能です。
IMPORTANT NOTES:
- The dry run was successful.
上のコマンドの--dry-runを外して認証申請をします。
(登録されたメールアドレスには、Let's Encryptからの通知(認証の有効期限が近づいてきた時の通知など)が届きます。)
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ /usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot
以下が出たら認証成功です。
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/○○.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/○○.com/privkey.pem
Your cert will expire on 2019-07-30. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew *all* of your certificates, run
"certbot-auto renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
証明書が発行されたかを確認します。
# 【】の所は置き換えてください
[ec2-user@ip-172-31-25-189 ~]$ sudo ls -lrth /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/
以下が表示されればOKです。
total 4.0K
-rw-r--r-- 1 root root 692 May 1 11:41 README
lrwxrwxrwx 1 root root 51 May 1 11:41 privkey.pem -> ../../archive/【ドメイン名(例:○○.com)】/privkey1.pem
lrwxrwxrwx 1 root root 53 May 1 11:41 fullchain.pem -> ../../archive/【ドメイン名(例:○○.com)】/fullchain1.pem
lrwxrwxrwx 1 root root 49 May 1 11:41 chain.pem -> ../../archive/【ドメイン名(例:○○.com)】/chain1.pem
lrwxrwxrwx 1 root root 48 May 1 11:41 cert.pem -> ../../archive/【ドメイン名(例:○○.com)】/cert1.pem
次に、nginxの設定ファイルをSSL用に更新します。
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/<ドメイン名>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<ドメイン名>/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
client_max_body_size 2g;
root /var/www/<アプリケーション名>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
root /var/www/<アプリケーション名>/current/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_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://app_server;
}
error_page 500 502 503 504 /500.html;
}
server {
listen 80;
server_name <ドメイン名>;
return 301 https://$host$request_uri;
}
nginxを再起動します。
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
設定ファイルの更新はこれで最後になります。あと一息です!
- ポート解放3
私はここで躓きました。
設定ファイルを更新して、「長い戦いが終わった(ニンマリ)」と意気揚々とリロードしたら、タイムアウトで表示されないじゃないか。
ふと、
ssl化のポート解放はあるのだろうかと、できているのだろうかと
閃いた。
やはり、ssl化に伴ってポートを開ける必要があるようです。
「セキュリティグループ」のリンクlaunch-wizard-1をクリックします。
「ルールの追加」をクリックします。
タイプを「HTTPS」、プロトコルを「TCP」、ポート範囲を「443」、送信元を「カスタム / 0.0.0.0/0, ::/0」に設定します。「0.0.0.0」や「::/0」は「全てのアクセスを許可する」という意味です。
- rails側の設定
ローカルで下記フォルダの記述を変更しましょう。
# config.force_ssl = true
config.force_ssl = true
変更後にmasterへpushしましょう。
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy
以上でSSLの設定は完了です。
ブラウザからこのサイトにアクセスしてみましょう。https接続になるはずです。
また、http://として接続した場合でも、自動でhttps接続になるはずです。
- Let's Encryptの自動更新
Let's Encryptの有効期間は3カ月と短いです。
自動で更新されるように、crontabで設定しておきましょう。
[ec2-user@ip-172-31-25-189 ~]$ sudo crontab -u root -e # rootユーザーでcrontabを編集することにより、cronでsudoを使わなくて済むようになります。
0 4 1 * * /usr/local/certbot/certbot-auto --no-self-upgrade && service nginx restart
この例では、毎月1日午前4時に自動で更新されるようになります。
設定後、cronデーモンを再起動します。
[ec2-user@ip-172-31-25-189 ~]$ sudo service crond restart
上記の方法では Amazon Linux 2 でエラーが出るようです。
こちらの記事は Amazon Linux の程なのでご了承ください🙇♂️
最後に
最後までお付き合いいただき、ありがとうございました。
twitterやっておりますので是非フォローよろしくお願いいたします!
https://twitter.com/syomabusiness
youtubeも始める予定です!