はじめに
対象・概要
Railsチュートリアルを参考にwebアプリを作ってHerokuにデプロイしてみたけど、軽快に動かない!ドキュメントも英語だし、有料契約は怖い!AWSも機能多すぎて難しそう!って人を対象に国産VPS、ConohaへのRailsアプリのデプロイ方法を記載しています。
私自身、Railsアプリを作ったもののデプロイできず困り果ててましたが、先人の方々の知恵を参考に、なんとかデプロイまでたどり着きました。
自分への備忘録も含め記します。
Capistranoは最初の構築は大変ですが、一度行ってしまえば、あとはコマンドを打つだけでデプロイ、バージョン管理まで行えるので非常に便利です。
なお、冗長な処理・タイポ・情報が古くなってる箇所あるかもしれません。コメントで指摘 or 編集リクエストを送って頂けると助かります。
開発環境
ローカル
- Mac OS
- Rails 5.1
- Ruby 2.4.1
サーバー
- CentOS 7.4
- MySQL
参考・謝辞
記事中でも言及していますが、こちらの記事は以下記事をそのままConohaのvpsに適応した形です。
@naoki_mochizukiさん、いつもとてもわかりやすい記事をありがとうございます。
(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita
1. Conohaの契約
conohaはGMOが運営しているVPSサービスです。月最低650円と比較的低価格で仮想サーバーを構築できます。国産なので請求書もドキュメントも日本語です。AWSみたいに請求書が英語、$表示で来ることもありません!
サーバーの初期イメージでRaisやkusanagiの環境を構築することも可能です。ただ今回は勉強という意味合いもあり、初期イメージは使用せず、標準のものから構築します。
VPSとは仮想専用サーバー(Virtual private server)のことで、通常のレンタルサーバーでは出来ないような操作も、あたかも自分専用のサーバーが一台あるかのように作業することができるサーバーのことです。
契約についてはConohaのドキュメントを参考にしてください。
第2回:ConoHaでVPSをはじめてみよう!|VPSならConoHa
こちらの記事では、以下構成のサーバーを対象にしています。
ひとつポイントは、SSH Keyを新規キー登録でpemのキーを生成しているという点です。次のSSH設定で使うので以下手順でダウンロードお願いします。
SSH-Key→新規キー登録→自動生成→ダウンロード
2. SSHの設定
VPSにローカルからSSHログインするまでの設定を行います。
ほぼ以下参考記事そのままです。
ConohaにVPSを設置して、SSHログイン、ポート番号変更、rootログイン禁止までを30分で! - Qiita
2-1 登録したpemキーでログイン
サーバー構築時に登録してダウンロードどした2018xxxxxxx.pemというkeyでサーバーにログインします。ターミナルを開いて以下を入力してください。
なおIPアドレスはサーバーのネットワーク情報に記載されています。
ここでは必ずsudoをつけて管理者権限で実行してください。また、途中yes / noと選択肢が出るのでyesと入力してください。
$ # sudo ssh -i [pemキーのパス] root@[serverのipアドレス]
$ sudo ssh -i ~/Downloads/20180105050643.pem root@133.130.116.122
root@133.130.116.122 [05:12:32]
Password:
The authenticity of host '133.130.116.122 (133.130.116.122)' can't be established.
ECDSA key fingerprint is SHA256:BqqPhuXGnZsqryTM07gYrm0dr2E9ruMZ3PaGPJrfpAE.
Are you sure you want to continue connecting (yes/no)? yes
2-2 ユーザーの作成・権限の追加
移行 サーバーでの操作です。
まずrootユーザーだと何かと不便なので、新規にユーザーを作成します。
# ユーザーの追加
$ adduser hoge
# パスワードの設定
$ passwd hoge
# 8文字以上とか制限がありますが、passwd: all authentication tokens updated successfully.と出ればOKです
# 作成したnewuserでログインできるか確認
$ su hoge
# promptの一番左がrootから追加したユーザー名に変わっていればOKです
さらにsudoコマンドが使えるように管理者権限を付与します。
以下参考にしました
CentOS上で管理者ユーザを作成する方法 - Qiita
# rootにユーザー切り替え
$ su root
# 管理者の管理フアイル(/etc/sudoers)に作成したユーザー追加
$ visudo
visudoで開いたファイルを編集します。viでの操作となります。
viなれるまで難しいですが、なれるとものすごい軽快にエディタを操作できます。
操作については以下を参考にしてください。
よく使う Vim のコマンドまとめ - Qiita
Vim初心者に捧ぐ実践的入門 - Qiita
該当箇所は以下のとおりです
root ALL=(ALL) ALLの下に新しく先程作成したユーザーを追加してくだい。それで:wqで保存終了。
.
.
##
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
hoge ALL=(ALL) ALL #追加
.
.
もう一度ユーザーを切り替えてsudoコマンド試してみましょう。
最初、なんか色々出てパスワードを聞かれますが、パスワードを入力し、
無事aaaが出力できれば大丈夫です。
$ su hoge
$ sudo echo aaa
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for hoge: # パスワードを入力
aaa
2-3 SSHログインの許可
sshの設定ファイルでsshログインを許可します。
さらに追加でセキュリティを上げるため、rootログインの禁止、パスワードログインの禁止の設定も行います。
$ sudo vi /etc/ssh/sshd_config
以下箇所を修正します。
# 公開鍵認証を許可
# #でコメントアウトされている場合は#を削除しコメントアウトを解除。
# noの場合はyesに
PubkeyAuthentication yes
# 公開鍵の場所を設定。たぶん初期値で大丈夫です。
AuthorizedKeysFile .ssh/authorized_keys
# rootユーザーでのログインを禁止。
PermitRootLogin no
# パスワードログインを禁止。yesからnoへ変更
PasswordAuthentication no
全部完了したらsshdを再起動します。
$ sudo service sshd restart
2-4 ポート番号の変更
sshのポートが22のままだとSSHへのブルートフォースアタック(ID, PASS 総当たり攻撃)という攻撃をされることがあるので、ポート番号を変更しましょう。
すこし手順が多いのですが、そのまま打ち込めば大丈夫です。
まず、iptablesをインストール。途中に出る選択肢はyでOK
$ sudo yum install iptables-services
次に設定ファイルを編集
$ sudo vi /etc/sysconfig/iptables
開いたら以下箇所を修正
# 下を削除
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
# 下を追加
-A INPUT -m state --state NEW -m tcp -p tcp --dport 10022 -j ACCEPT
iptablesの再起動
$ sudo service iptables restart
sshの設定を修正
$ sudo vi /etc/ssh/sshd_config
開いたら任意の箇所に以下を追加
Port 10022
sshdの再起動
$ sudo service sshd restart
これで対策OKです。
2-5 公開鍵の作成
続いて、リモートサーバー上でSSHで使用する鍵を作成。
そして公開鍵をauthorized_keysに追加します
鍵の作成
# 作成したユーザーに切り替え
$ su hoge
$ cd ~
# sshのフォルダ作成
$ mkdir .ssh
$ cd .ssh
# キーペアの作成
$ ssh-keygen -t rsa -b 4096
Enter file in which to save the key: #エンターでOK
Enter passphrase: # 5文字以上のパスフレーズを入力
Enter same passphrase again: #5文字以上のパスフレーズを入力
# 2つの鍵が作成されます
$ ls .
id_rsa id_rsa.pub
# id_rsa.pubが公開鍵です。これを2-3で設定したauthorized_keysにします。(ファイル名を変更)
$ mv id_rsa.pub authorized_keys
# 権限の設定
$ chmod 700 ~/.ssh
$ chmod 600 authorized_keys
# 秘密鍵の内容を確認
# 表示された文字列をクリップボードにコピーしてください
# -----BEGIN RSA PRIVATE KEY-----から
# -----END RSA PRIVATE KEY-----までです。
$ cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
-----END RSA PRIVATE KEY-----
2-6 秘密鍵をローカルのsshに登録
秘密鍵をローカルのsshに登録します。
ここまで完了すれば、あとはssh xxx で簡単にsshでリモートサーバーにアクセスが出来るようになります。
今からの操作はローカルで行うので注意!
サーバー側にいる場合は、exitもしくは別ウィンドウでローカルを開きましょう。
$ cd ~/.ssh
# 鍵の保存場所の作成
$ mkdir conoha_hoge #名前は任意
# 鍵ファイルの作成
$ cd conoha_hoge
$ vi id_rsa
# 先程クリップボードにコピーした内容をそのまま貼り付けて保存
# 権限の設定
$ chmod 600 id_rsa
# sshの設定ファイルの作成
$ cd ..
$ vi config
以下内容を追記します。
HostNameはconohaのIPアドレスです。
Host conoha_hoge
HostName 133.130.116.122
User hoge
Port 10022
IdentityFile ~/.ssh/conoha_hoge/id_rsa
これで設定完了です!!
あとは以下でリモートサーバーにアクセスできるはず!!
$ ssh conoha_hoge
# パスフレーズが聞かれるので作成時のものを入力
2-7 SSH agentへの登録
上記のままで接続はできるのですが、毎回パスフレーズを聞かれるのが面倒です。
なのでssh-agentという便利なものがあるのでそれを使いましょう。
使い方は簡単。以下コマンドで鍵を登録するだけです。
登録すればあとはssh サーバー名でパスフレーズなしのアクセスができます。
SSH agentについては以下が大変参考になりました。
ssh-agentを利用して、安全にSSH認証を行う - Qiita
$ sudo ssh-add -K ~/.ssh/conoha_hoge/id_rsa
3 Rubyの設定
続いてRailsアプリを動かすために無くてはならない、Rubyの設定をします。
git、rbenv、ruby-buildとステップは多いのですが頑張りましょう。
以下すべてサーバー側での処理です。
3-1 Gitのインストール
何はともあれまずgitをインストールしましょう。
rbenvのインストール、capistranoの設定で使用します。
$ sudo yum -y install git
$ git --version
# version名出力されればOK
3-2 rbenvのインストール・設定
rbenvはrubyのバージョン管理ツールでディレクトリごとに使用バージョンを設定するなど柔軟な開発ができます。
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
3-3 ruby-buildのインストール
ruby-burildはrbenv installを実行するためのrbenvのプラグインです。基本的にrbenvとセットでインストールします。
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
3-4 依存パッケージのインストール
rubyをインストールするための関連するパッケージです。これがないと、rbenv installの際にコケます。
$ sudo yum -y install bzip2 gcc openssl-devel readline-devel zlib-devel
3-5 rbenvの読み込み設定
rbenvコマンドを使える用にするために、shel起動時読み込むbash_profileにコードを追加します。
echo xx >> ~/.bash_profile にて追記モードで.bash_profileに書き込んでいます。
# PATHにrbenvコマンドを追加
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# rbenvの初期化
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# bashの再読込
$ source ~/.bash_profile
# rbenvのバージョン確認 バージョンが出ればOK
$ rbenv -v
3-6 rubyのインストール
長くなりましたが、やっとrubyのインストールです。
バージョンについては、ご自身のローカル開発環境と合わせてください。
ネット環境によってはruby installで結構時間かかります。
# ruby 2.4.1のインストール
$ rbenv install 2.4.1
# globalで使用するrubyの設定
$ rbenv global 2.4.1
# rbenvの再起動?
$ rbenv rehash
# rubyのバージョン確認
$ ruby -v
3-7 bundleのインストール
gemを効率よく管理するためのbundleをインストールします。
$ gem install bundle
4 node.jsのインストール
railsでnode.jsが必要なのでこちらもインストールしておきます。
$ sudo yum install nodejs npm --enablerepo=epel
さらにnpmでyarnもインストールします。
$ sudo npm install -g yarn
5. MySQLの設定
次にリモートサーバーにMySQLをインストールします。
下記記事参考にさせて頂きました。
CentOS 7 に MySQL 5.7 を yum インストールして初期設定までやってみた - enomotodev’s blog
5-1 インストール
CentOSの7系では標準でMariaDBがインストールされているので、まずそれの削除から行います。
以下全てリモートサーバー
# mariadbの削除
$ sudo yum remove mariadb-libs
$ sudo rm -rf /var/lib/mysql
続いてyumにMySQLのリポジトリを登録します
$ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
完了したらパッケージのインストール!
# インストール
$ sudo yum install mysql-community-server mysql-devel
# 確認。バージョン出ればOK
$ mysqld --version
起動と自動起動の設定
# 起動
$ sudo systemctl start mysqld.service
# 自動起動設定
$ sudo systemctl enable mysqld.service
5-2 パスワード、セキュリティ設定
ログインするために、まず自動生成された初期パスワードを確認します。
$ sudo cat /var/log/mysqld.log | grep password
2017-12-31T11:31:07.946947Z 1 [Note] A temporary password is generated for root@localhost: .7ogGO4yokDh
# これの「.7ogGO4yokDh」の部分が初期パスワードです。
確認できたらmysql_secure_installationで初期設定を行います。
以下対話形式で進むので適宜コマンド入力してください。
$ mysql_secure_installation
Securing the MySQL server deployment.
Enter password for user root: # ログファイルから取得した初期パスワードを入力します
The existing password for the user account root has expired. Please set a new password.
New password: # root ユーザの新規パスワードを入力します
Re-enter new password: # 確認用にもう一度入力します
The 'validate_password' plugin is installed on the server.
The subsequent steps will run with the existing configuration
of the plugin.
Using existing password for root.
Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y # 匿名ユーザーアカウントを削除
Success.
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y # ローカルホスト以外からアクセス可能な root アカウントを削除
Success.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y # test データベースの削除
- Dropping test database...
Success.
- Removing privileges on test database...
Success.
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.
All done!
ここで設定するパスワードには大文字小文字英数字+特殊文字で8文字以上という制約があります。それを満たすパスワードを設定しなくてはならないので注意してください。
そんな複雑なパスワード覚えられない!って人は、ひとまず適当に設定したあと、以下記事で解説されている方法でrootなど分かりやすいものに変更してください。
5-3 日本語化
次に日本語を扱うために文字コードをUTF-8に変更します。
以下を参考にさせて頂きました。
mysqlで文字コードをutf8にセットする - Qiita
ちなみに私はこれをし忘れてCapistranoがseedでinsertがコケること1時間。。。
以下mysqlにログインしコンソール内でのコマンド
# まず文字コードを確認
mysql> show variables like "chara%";
# latin1のとこをUTF-8に変更します
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
設定ファイルを修正します
exitでmysqlを停止してコンソール上にて
$ sudo vi /etc/my.cnf
ファイル内の末尾に以下を追記
character-set-server=utf8
[client]
default-character-set=utf8
再起動
$ sudo systemctl restart mysqld.service
再度MySQLにログインして確認
mysql > show variables like "chara%";
# 以下が表示されればOK
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
5-4 time-zoneを設定
必須ではないですが、アプリでTime-zoneを使うこともあるので最初に設定しておきましょう。
以下参考記事
MySQLでタイムゾーンを設定する - Qiita
Time-zoneのインポートと初期化
$ /usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo > ~/timezone.sql
# passwordを聞かれるのでmysqlのパスワードを入力
$ mysql -u root -p -Dmysql < ~/timezone.sql
設定の追加
$ sudo vi /etc/my.cnf
末尾に以下を追加
default-time-zone = 'Asia/Tokyo'
再起動
$ sudo systemctl restart mysqld.service
確認。以下MySQLコンソール
mysql > show variables like '%time_zone%';
# 以下表示が出ればOK
+------------------+------------+
| Variable_name | Value |
+------------------+------------+
| system_time_zone | JST |
| time_zone | Asia/Tokyo |
+------------------+------------+
2 rows in set (0.00 sec)
5-5 MySQLの自動起動設定
サーバーの再起動の際にも、mysqlが自動的に起動するよう設定します。
chkconfig mysqld on
これでMySQLの設定が完了です。
6. Nginxの設定
続いてwebサーバーのNginxの設定を行います。webサーバーとはhttpリクエストに対してレスポンスを返すソフトウェアです。従来は多機能なApacheを採用することが多かったですが、現在はより高速でシンプルに動作するNginxが主流のようです。
以下参考にさせて頂きました。
(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita
また、webサーバーの概要、アプリケーション・サーバー(今回の場合はUnicorn)との違いは以下が非常に分かりやすかったです。
Rails開発におけるwebサーバーとアプリケーションサーバーの違い(翻訳) - Qiita
6-1 インストール
yumで一発です。以下サーバーにて
$ cd ~
$ sudo yum install nginx
# 確認。バージョン出ればOK
$ nginx -v
6-2 設定ファイルの編集
リクエストの処理方法、webアプリのディレクトリ設定等を行います。
まず、ファイル作成
$ cd /etc/nginx/conf.d/
$ sudo vi hoge_app.conf # 名前は任意。webアプリの名前とか
続いてファイルの中身を以下のように修正してください。
hoge_appの部分は任意の名称に変えてください。
serer_nameの部分をconohaのipアドレスに変更することも忘れずに
#各種ログのディレクトリ設定
error_log /var/www/hoge_app/current/log/nginx.error.log;
access_log /var/www/hoge_app/current/log/nginx.access.log;
#処理を受け取る最大許容量
client_max_body_size 2G;
upstream app_server {
# 連携するunicornのソケットのパス
server unix:/var/www/hoge_app/current/tmp/sockets/.unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name xxx.xxx.xxx.xxx; # conohaのipアドレス
#次のリクエストが来るまでの待ち時間(秒
keepalive_timeout 5;
#静的ファイルを読みに行くディレクトリ
root /var/www/hoge_app/current/public;
#キャッシュのディレクトリ
try_files $uri/index.html $uri.html $uri @app;
location @app {
# HTTP headers
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;
location = /500.html {
root /var/www/hoge_app/current/public;
}
}
まだ /var/www/hoge_app/フォルダは無いですが、その2で作成するので気に留めずで大丈夫です。
6-3 80番ポートの開放
Nginxが使用する80番ポートを開放します。
sshのポート変更にて使用したiptablesを使います。
これをしないとhttpでの通信が出来ないので注意!
まず設定ファイルを開く
$ sudo vi /etc/sysconfig/iptables
前sshのポート番号変更で設定した10022の下に以下を追記して保存
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
再起動。
$ sudo service iptables restart
開放されてるか確認しましょう。
$ sudo iptables -nL
# 如何表示に含まれていればOK
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
6-4 Nginxの自動起動設定
サーバーの再起動の際にもNginxが自動的に起動するよう設定します。
chkconfig nginx on
これでNginxの設定が完了です。
7. Githubの公開鍵登録
capisatranoでは、直接ローカルからファイルを送るのではなく、githubなどのホスティングサービスを経由します。なので、サーバー側からgithubへsshで接続できるようにキーペアの作成・登録を行います。
キーペアの作成(サーバー)
$ cd ~/.ssh/
$ mkdir github
$ cd github
# キーペアの作成
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hoge/.ssh/id_rsa): /home/hoge/.ssh/github/id_rsa # 先程作成したフォルダを指定
Enter passphrase (empty for no passphrase): # Enter
Enter same passphrase again: #Eneter
$ cat id_rsa.pub
# 出力をコピーして、githubのコンソールより公開鍵を登録
# 設定ファイルを作成
$ sudo vi ~/.ssh/config
# 以下を記述
Host github.com
Hostname github.com
User git
IdentityFile ~/.ssh/github/id_rsa
catで表示した公開鍵(id_rsa.pub)の情報は、以下記事を参考にgithubアカウントの公開鍵に追加してください。
gitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita
サーバーからgithubへssh接続出来れば完了です。
$ ssh -T github
#確認はyes
#以下のような文章が出力されればOK
Hi kawamataryo! You've successfully authenticated, but GitHub does not provide shell access.
かなり長文となりましたので、続きは(初心者向け)vpsを契約して、Capistrano3でRailsアプリをデプロイするまで その2 ローカル設定編 - Qiitaで記します。