話題の記事

nginxにリバースプロキシ設定してapacheと連携させる

2014.05.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

railsとwebサーバを連携する場合はapache × passengerまたはnginx × unicornのどちらかを使用することが多いかと思います。 昔はwebサーバといえばapacheでしたが、最近はかなりnginxが使われてきています。 apacheとnginxのを比較したときに、静的ファイルはnginxが動的ファイルはapacheが早いと言われています。 そこで今回はnginxにリバースプロキシの設定をし、apacheと連携してみました。つまりhtmlや画像などの静的ファイルはnginxで処理し、railsの処理はapache経由で処理させることをやってみました。

開発環境

今回はmacのvirtual boxにubuntuをインストールし環境を構築しました。

  • ubuntu 12.04 32bit
  • apache 2.2
  • nginx 1.6
  • ruby 2.00
  • rails 4.1.0

※apache等は既にインストール済みとして進めます。

apache上でrailsを動かす

まず始めにrailsプロジェクトを作成してapache上で動作するようにします。

passengerとの連携

  $ rails new rails_app

プロジェクトを作成したらGemfileに以下を追加しインストールします。

$ gem 'passenger'
$ bundle install

apacheモジュールのビルドとインストールをします。

$ passenger-install-apache2-module

実行するとこんなメッセージが表示されます。 Enterキー押して、次へすすみます。

Welcome to the Phusion Passenger Apache 2 module installer, v4.0.42.

This installer will guide you through the entire installation process. It
shouldn't take more than 3 minutes in total.

Here's what you can expect from the installation process:

 1. The Apache 2 module will be installed for you.
 2. You'll learn how to configure Apache.
 3. You'll learn how to deploy a Ruby on Rails application.

Don't worry if anything goes wrong. This installer will advise you on how to
solve any problems.

Press Enter to continue, or Ctrl-C to abort.

選択をRubyのみにしてEnterキーを押すと、インストールが始まります。

Use <space> to select.
If the menu doesn't display correctly, press '!'

 ‣ ⬢  Ruby
   ⬡  Python
   ⬡  Node.js
   ⬡  Meteor

インストールが完了すると以下のようなメッセージが表示されるので、コピーします。これは環境に依存するのでインストールした環境のものをコピーしてください。 Enterキーを押すとVirtualHostのサンプルが表示されて完了です。

   LoadModule passenger_module /home/test/rails_projects/rails_app/vendor/bundle/ruby/2.0.0/gems/passenger-4.0.42/buildout/apache2/mod_passenger.so
   <IfModule mod_passenger.c>
     PassengerRoot /home/test/rails_projects/rails_app/vendor/bundle/ruby/2.0.0/gems/passenger-4.0.42
     PassengerDefaultRuby /home/test/.rbenv/versions/2.0.0-p451/bin/ruby
   </IfModule>

apache.confの設定

/etc/apache2/apache.confを開きます。(RedHat系ならhttpd.confになります) 先ほどコピーしたpassengerの設定を貼付けて保存します。 次にVirtualHostの設定をします。 /etc/apache2/sites-availableにlocalhostファイルを作成します。(ファイル名は任意です。) 以下、VirtualHostの設定です。nginxと連携させるポートをここでは8080にしています。ドキュメントルートはrailsプロジェクトのpublicを指定します。

 <VirtualHost *:8080>
  DocumentRoot /home/test/rails_projects/rails_app/public
  RailsEnv development
  <Directory /home/test/rails_projects/rails_app/public>
    AllowOverride all
    Options -MultiViews
  </Directory>
</VirtualHost>

設定を有効にさせます。localhostは作成したファイル名です。

sudo a2ensite localhost

ポートの設定を変更します。 /etc/apache2/ports.confを開いて8080に設定を変更します。

NameVirtualHost *:8080
Listen 8080

apacheを起動させます。

sudo apache2ctl start

これでhttp://localhost:8080にアクセスするとrailsのトップ画面(Welcome aboard)が表示されます。

nginxの設定

次にnginxにリバースプロキシの設定をします。 /etc/nginx/conf.d/にsample.confを作成します。(ファイル名は任意です)

    upstream web-apache {
      server localhost:8080;
    }
    server {
      listen       80;
      server_name  sample.jp;

      location ~* .*\.(jpg|gif|png|css|js|html|) {
        root   /home/test/rails_projects/sample_app/public;
        index  index.html index.htm;
      }

      location / {
        proxy_pass http://web-apache/;
      }
    }

静的ファイルのjpgなどのリクエストはnginxがそれ以外のリクエストはapacheのlocalhost:8080を呼び出すようにしています。 nginxを起動します。

  sudo nginx

http://localhostにアクセスしてみます。railsのトップページが表示されます。 これでnginxとapacheが連携できました。

アクセスログを見てみる

macからubuntuにアクセスした後にapacheのアクセスログを見てみると・・・

sample.jp:8080 127.0.0.1  - - [29/May/2014:12:49:55 +0900] "GET /home/ HTTP/1.0"

127.0.0.1となっておりローカルからのアクセス、つまりnginxからアクセスしたIPになってしまいます。 これを解決するにはapacheにモジュールを追加する必要があります。解決してくれるモジュールはいくつかあるのですが、ここではmod-rpafを使用します。インストールしましょう。

  sudo apt-get install libapache2-mod-rpaf

インストールが完了したらnginxの設定をします。先ほど作成したsample.confにproxy_set_headerの設定を追加します。

    upstream web-apache {
      server localhost:8080;
    }
    server {
      listen       80;
      server_name  sample.jp;

      location ~* .*\.(jpg|gif|png|css|js|html|) {
        root   /home/test/rails_projects/sample_app/public;
        index  index.html index.htm;
      }

      location / {
        proxy_set_header  X-Real-IP       $remote_addr;
        proxy_set_header  X-Forwarded-For $remote_addr;
        proxy_set_header  Host            $http_host;
        proxy_pass http://web-apache/;
      }
    }

nginxを再起動して再度アクセスログを確認するとクライアントのIPにかわっていることが確認できます。

sample.jp:8080 192.168.1.38 - - [29/May/2014:13:50:55 +0900] "GET /home/ HTTP/1.0"

まとめ

リバースプロキシを設定すること負荷分散させることが出来たり、色々なメリットがあります。 新規でサイトを構築する際は検討してみてはいかがでしょうか。

参考資料