AWS(ELB)+nginx+unicornの設定の際にはまったポイント。

AWS+nginx+unicornの設定の際にはまったポイント。

基本的な導入については他の方々が書いているのでこちらとか、グーグル先生を参照ください。
qiita.com

構成

構成としてはこんな感じ。外からポートhttps443で受けて、中はhttp80で。
permissionとか、csrfActionController::InvalidAuthenticityToken errorエラーが出たりと結構はまりました。
f:id:skymay:20160817151922p:plain


- まずはログの確認。どこまで通信できてますか。エラーは出てませんか。

/var/log/nginx/access.log
/var/log/nginx/error.log
rails_home/log/unicorn.log
rails_home/log/production.log または rails_home/log/development.log

1. nginxでpermission denyエラーがでている。

permissionエラーの場合。nginxでよくでたりします。
この場合、ファイル・フォルダに権限を与えましょう。

chmod 755 /home/rails_home/

下位フォルダだけ権限を与えていて、上位フォルダの権限がない可能性もあるので、しっかりと確認を。

2. nginxでsocketがないと言われている

nginxとunicorn.rbの設定を再度確認しましょう。
unicorn.rbで設定した

listen "/tmp/unicorn.sock"

とnginx.confで設定した下記パスが一致してますか。

upstream unicorn {
  server unix:/home/unicorn_sample/tmp/unicorn.sock;
}

この例の場合違っていますので、「/tmp/unicorn.sock」に修正しましょう。

設定変更後は各プロセスの再起動を忘れずにしましょう。

3. csrfActionController::InvalidAuthenticityToken error

offにするという手もあります。日本語の多くのページでオフにする記載をみかけますが、セキュリティ上よくありません。
nginxの設定を見直しましょう。
root設定はあってますか。locationのheader設定はあってますか。

http {
    upstream unicornapp {
        server unix:/tmp/unicorn.sock;
    }

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  localhost;
        root         /home/rails_home/public;

        location / {
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://unicornapp;
        }
}
4. ELBでInServiceにならない

ヘルスチェックでこけています。
まずはnginxでヘルスチェックのアクセスログがのっかてきているかを確認してみましょう。
/var/log/nginx/access.log

のっていない場合はAWSセキュリティポリシーで対象のポートを閉じてませんか?

EC2上からcurl/wgetコマンドでヘルスチェック先へのアクセスを確認してみましょう。ページがない可能性があります。

$curl http://localhost/
おまけ1

empty gifでヘルスチェック(nginxまでのヘルスチェック)

location = /healthcheck.html {
 access_log off;
 empty_gif;
}

health_check用のコントローラーを準備
上の設定だと裏が死んでいても気づかないので、こちらの方が良いかと。

rails g controller health_check
class HealthCheckController < ApplicationController
  def index
    render :text => "Alive\n", :status =>200
  end

  protected
  def allow_http?
    true
  end
end

route.rb

  get "health_check" => "health_check#index"
おまけ2

サーバー設定を隠す。
レスポンスのヘッダーにサーバー設定がのっかてきます。
このままだとセキュリティ上よろしくないので、見えないようにすることをおすすめします。

Server: nginx/1.8.1

nginx.confに下記を追加して再起動してください。
バージョン情報はのってこなくなります。

http {
    server_tokens off;
}

書き換えてnginx自体の表示もなくせますが、それはまたの機会に。