概要
開発中のRailsアプリケーションを実際に自分でも使いたいので、できるだけ金をかけずにデプロイする方法を考えた。URLとかドメインとかの個人的なこだわりとアプリケーションの使用環境を考えるとHerokuはやなので、Apache&Passengerのコンボで以前購入したRaspberry Piをサーバーとして、アプリケーションをデプロイしてみる。作業が色々回りくどかったことと、あまり包括的にラズパイでのサーバー構築に関してカバーしてる記事がなかったので備忘として残しておくことに。
自分も初めてやったし独学なので、今後のために極力わかりやすく丁寧に書く。
*セキュリティは現段階では(おそらく)貧弱なので自己責任でお願いします。ご指摘いただけると幸いです。
*各ステップにおける説明の加減は自分の理解度が低いところに優先的に比重をかけています。
前提
使用するのは主に、
- Raspberry Pi
- Filezilla (Piへのファイル転送用)
- Apache
- Passenger
- Ruby&Rails (Ruby 2.6.0, Rails 5.2.3)
- ドメインと転送設定他
Raspberry Piは、以前トライしてみたHeadlessインストール(ディスプレイなしでのインストール)で要素が増えすぎて大変だったので、Noob経由でRaspbian Liteをインストール。sshを有効にした状態からスタート。操作はMacbookからsshで行う。
ApacheとPassengerはこれから導入していく。
RubyとRailsもこれからインストール。すでに作成したアプリケーションがあるのでそれをデプロイする。
ドメインは、フリードメインを入手してある(.tk)。Piが繋がってるルーターで転送設定して、かつドメインからDNSでルータに繋がるように設定済み。
ドメインのところは、それはそれで初心者にはややこしい。また機会があれば書くけれど、今回は面倒なので割愛。特にドメインとかいらないよって場合は、この記事ではドメインをpublic IPで置き換えて入れればだいたいうまくいくはず。というかそちらの方が要素が少ないので確実。
目標
最終的に、ブラウザーで専用のドメインのURLを入力して、アプリケーションのトップページが表示されれば成功。
流れ
全体的な流れは以下のように進めます。
0. スタート地点の確認
- RubyとRailsをインストール
- Apacheをインストール
- Passengerをインストール
- Testアプリで動作確認
- アプリケーションの転送と設定
- 最終確認
長くなりそう。
それでは早速。
0. スタート地点の確認
前提でも書きましたが、目標に照らしてさらっと現状を確認します。
現段階でブラウザにURL入れるとこんな感じ。
当たり前。
当たり前すぎてある意味安心。
1. RubyとRailsをインストール
下準備として、まずRubyをPiに入れていきます。今回は2.6.0でいきます。
sshでpiにログイン
MacbookのTerminalからsshでPiにログインします。
ssh pi@YOUR_DOMAIN
piはRaspberry Piのユーザ名(デフォルトはpiです)、YOUR_DOMAINのところに自分のドメインか、転送設定をしたpublic IPを入れます。
バージョン管理のための下準備
アプリケーションによって使用するrubyのバージョンが異なる場合があるので、バージョン管理をするために使うrbenvを入れます。
まずはパッケージの更新。
$ sudo apt-get update
$ sudo apt-get upgrade
gitを入れる。rbenv入れるのとかupdateに使います。
sudo apt install git
nodejs (念のため)
$ sudo apt-get install nodejs
rbenvインストール (バージョン管理用)
rbenv
$ sudo git clone https://github.com/rbenv/rbenv.git ~/.rbenv
これでrbenvは入ったんですが、これをrbenv init ほにゃらら
で実行できるようにするため、俗にいう「pathを通す」ということをします。
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
.bashrcはbashが起動されるたびに実行される。>>
は追記という意味なので、.bashrcにrbenv init -
を追記することになる。.bassh_profileはログイン時のみなのでsshだとめんどくさそうということで、ここでは.bashrcにしておく。(sshでrapberry pi再起動した時は嫌な思い出しかない)
次。ruby-buildを入れておきます。rbenvでrubyをインストールするために必要です。~/.rbenv/plugingsに作成されます。
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
最後にrehashする。
$ sudo rbenv rehash
rbenvでは、バージョンごとに実行するファイルを分けるためにerb, gem, irb等ごとにフォルダを用意し、以下にバージョンごとのファイルを振り分けてくれます。shimと呼ばれるやつです。こうしておくことで、rbenv関連のコマンドが入ると、~/.rbenv/shimsを通して、バージョンに適切なファイルを実行できるようにしてあります。このshimsは、新しいgemなどを入れるたびに更新する必要があるため、それを行なっているのが上記のコマンド。
ここで念のため、一度MacbookのTerminalも閉じて、もう一度sshを接続し直します。
Rubyをインストール
まずはインストールできるバージョンを確認。上記でgitからrbenv/ruby-buildを入れているなら最新なはずです。
2.6.0があるか確認。
$ rbenv install --list
今回は2.6.0を入れます。
2.4, 2.5あたり以前を入れる場合は注意。CPUとの相性がどうたらでPassengerでBus ErrorやSegmentation Fault Errorが出たりします。解決法はありますが、めんどいので2.6.0。解決法はここ(HatenaBlog)
時間かかるので注意。僕の場合は30分弱かかった。
$ rbenv install 2.6.0
$ rbenv global 2.6.0 # 以降使用するバージョンを設定
$ rbenv rehash # 恒例のrehash
インストールできたか確認する。
$ ruby --version
=> ruby 2.6.0p0 (2018-12-25 revision 66547) [armv7l-linux-eabihf]
バージョン情報が表示されたということは、入ってる。
よし。
Railsのインストール
導入
Railsを入れていきます。
まずパッケージ管理用のbundlerを入れます。
$ gem install bundler
Railsを入れます。
これは僕の場合は15分くらいかかりました。
$ gem install rails
動作確認。
$ rails --version
=> Rails 5.2.3
おっけい。
2. Apacheをインストール
こちらは、Raspberry Pi公式でドキュメンテーションがあるのでそれに従います。(この記事では利用しませんが、index.htmlを変更して自分の簡単なwebサイトをApacheに表示させる方法も書いてあります。)
$ sudo apt-get update
$ sudo apt-get install apache2 -y
-yは、--assume-yes
の略で、promptに対して自動でy
で回答するというもの。
Apache動作確認
ここまでうまくいって入れば、ブラウザでURLを入力すればApacheの初期画面が表示されるはず。
やってみる。
やった...! (涙目
3. Passengerをインストール
次。ApacheでRailsアプリケーションを動かすために、ApacheのモジュールであるPhusion Passengerを入れます。インストールと初期設定(configuration)で少し量があるので見出し分けます。
インストール
まずはPassengerをgemでインストール。
5分ほどかかります。sudoは使わない。
$ gem install passenger
次に、ApacheとPassengerを連帯させます。コマンドを入力するとインストラクションが表示されるので、従っていけば大丈夫です。しっかり読みながら進めます。
$ passenger-install-apache2-module
いくつかEnterを押すと、自動でチェックを始める。
チェックが終わると、必要なもののインストール方法を教えてくれる。
従順に従って、すべてインストールします。
文頭にはsudoをつけて実行します。
僕の場合は、
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install ruby-dev
sudo apt-get install apache2-threaded-dev
sudo apt-get install libapr1-dev
sudo apt-get install libaprutil1-dev
やってみると、エラーが出た。
$ sudo apt-get install apache2-threaded-dev
=> Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package apache2-threaded-dev
対処法は、こう書き換えて実行すること。原因は不明。
sudo apt-get install apache2-dev
全部終わったら、再度
$ passenger-install-apache2-module
ここは20分以上かかりました。
備考:
仮にインストールしたはずなのにまた同じインストール要求をされる場合は、
sudo apt autoremove
を行なって、apache2-devのみ入れて、もう一度
passenger-install-apache2-module
を行なってみるとうまくいくかも。
Apache configurationファイルを編集し、以下を追記してくださいという表示です。僕の場合はこのように出ています。
LoadModule passenger_module /home/pi/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/passenger-6.0.2/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /home/pi/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/passenger-6.0.2
PassengerDefaultRuby /home/pi/.rbenv/versions/2.6.0/bin/ruby
</IfModule>
これは環境によって変わる可能性があるので、ご自分のコンソールに表示されたものをコピーしておいてください。
初期設定 (configuration)
上記でコピーを取ったものをApacheのconfigurationファイルに追加します。
"Press ENTER when you are done editing."
とあるので、念のため別のsshセッションを開始してそこから編集します。
基本的にApacheのconfigurationファイルは、
/etc/apache2/
内にある、apache2.confです。
編集権限を持たせるためsudoでテキストエディタ(nano)を起動します。
$ sudo nano /etc/apache2/apache2.conf
ctr+x
のちにY
、そしてEnter
を押すと保存してnanoを終了します。
1つめのsshに戻って、Enter
を押すと、インストールが正しく行われたかチェックしてくれます。
Everything looks good. :-)
を表示されればOk.
最後に念のため、PassengerとApache双方がうまく動いているか確認。
$ sudo passenger-config validate-install
おっと、
* Checking whether the Passenger module is correctly configured in Apache... ✗
Incorrect Passenger module path detected
Phusion Passenger for Apache requires a 'LoadModule passenger_module'
directive inside an Apache configuration file. This directive has been
detected in the following config file:
/etc/apache2/apache2.conf
However, the directive refers to the following Apache module, which is wrong:
/home/pi/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/passenger-6.0.2/buildout/apache2/mod_passenger.so
Please edit the config file and change the directive to this instead:
LoadModule passenger_module /var/lib/gems/2.5.0/gems/passenger-6.0.2/buildout/apache2/mod_passenger.so
configファイルは存在するけど、Apacheへのパスの設定が間違っている、と言っています。
ただ僕はrubyをrbenvで管理しており、rubyも2.6.0を入れたので、パスはあっていると判断。
続行します。
4. Testアプリで動作確認
Railsでテスト用のアプリを作成し、Passengerにそのファイルを参照させることで、URLにアクセスするとRuby on Railsの初期画面が表示されるところまで持っていきます。これで、Apache, Passenger, Railsが正しく動作することを確認。
TestアプリをRailsで作成
ただプロジェクトを作るだけです。
プロジェクトを作成するパスまでナビゲートし、rails用のフォルダを作成。
$ cd /var/www/
$ sudo mkdir rails # rails用のフォルダ作成
$ sudo chmod -R 777 rails # permissionを設定 (注意!)
$ cd rails # 作ったフォルダに移動
3行目の sudo chmod -R 777 rails
は、危険な方法です。
今回はRailsが必要なフォルダを作成するためにrailsフォルダの全ての権限を解放しています。しかし、これは今回の目的が実験的にRailsを動かすためであるからで、セキュリティ的には危険です。ウェブサイトとして公開した際、訪問者がrailsフォルダ内のデータをどうとでもできる状態です。本来はApacheのみに権限を与えることでRailsが必要な挙動を許可されるようにします。 参考1, 参考2
今回は個人的なテストなのでよしとして、ここで、Railsプロジェクトを作成。
$ rails new TestApp --skip-bundle
--skip-bundle
は、初期に自動でbundle installするのを飛ばします。古いバージョンのRailsでは、初期のbundle installが問題を起こすことがあったので念のため。
PassengerをTestAppに向ける
まず、使うrubyのパスを調べます。
$ passenger-config about ruby-command
=> passenger-config was invoked through the following Ruby interpreter:
Command: /home/pi/.rbenv/versions/2.6.0/bin/ruby # これがrubyのパス。
Version: ruby 2.6.0p0 (2018-12-25 revision 66547) [armv7l-linux-eabihf]
ということで、/home/pi/.rbenv/versions/2.6.0/bin/ruby
がrubyのパス。
次に、/etc/apache2/apache2.config
を再度nanoで編集し、以下を追記します。
<VirtualHost *:80>
ServerName yourserver.com # 自分のドメイン
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/rails/TestApp/public # 先ほど作ったTestApp内の'public'というフォルダ
PassengerRuby /home/pi/.rbenv/versions/2.6.0/bin/ruby # 今見つけたrubyへのパス。
# Relax Apache security settings
<Directory /var/www/rails/TestApp/public> # ここのパスも、先ほどと同じくTestAppのpublicフォルダ
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache > 2.4:
#Require all granted
</Directory>
</VirtualHost>
先ほどと同じように、ctr+x
→ Y
→ Enter
で保存してnanoを終了します。
できたら、Apacheを再起動します。
$ sudo apachectl restart
ここまできたら、早速ブラウザからドメインにアクセスして見ましょう。
なんでやねん。まずは、ブラウザ上からエラーメッセージの詳細を確認できるように設定しましょう。
/etc/apache2/apache2.conf
に、
PassengerFriendlyErrorPages on
Apacheを再起動。
$ sudo apachectl restart
わかった、bundleだ。
$ cd /var/www/rails/TestApp
$ bundle install
あ、わかった、RailsアプリがDevelopmentになってると、Passengerはアプリを起動してくれません。それを、Developmentモードでも大丈夫だよとPassengerに伝えるために、Apacheのコンフィギュレーションをいじります。
なので、/etc/apache2/apache2.conf
を再度編集し、RailsEnv development
の記述を追加します。
$ sudo nano /etc/apache2/apache2.conf
できたら、
sudo apachectl restart
でApacheを再起動。
ブラウザを更新すると...
これが見えた時の喜びのすごさよ。5. アプリケーションの転送と設定
ただのRailsの画面では面白くないので、あらかじめ作成しておいたアプリをPiに転送して、それが動くか確かめて見る。
FileZillaで転送します。
Quick ConnectionでPiに接続後、アプリのフォルダを
/var/www/rails
内にドラッグドロップします。
転送が完了したら、apache2.conf
を編集。
僕の場合アプリ名(つまりフォルダ名)は
Daruma
なので、
/etc/apache2/apache2.conf
をnanoで編集し、VirtualHostの部分を以下のように編集します。
<VirtualHost *:80>
ServerName YOUR DOMAIN # ドメイン名またはIP
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/rails/Daruma/public # ← ここを変更。
RailsEnv development
PassengerRuby /home/pi/.rbenv/versions/2.6.0/bin/ruby
PassengerFriendlyErrorPages on
# Relax Apache security settings
<Directory /var/www/rails/TestApp/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache > 2.4:
#Require all granted
</Directory>
</VirtualHost>
できたら保存。
忘れずに、
$ bundle install
6. 最終確認
ブラウザーを更新して、アプリのトップページが表示されるか確かめます。
よっしゃ。 目標達成!!!/