Nginx設定のまとめ

## はじめに
僕は盲目的に`unicorn`を起動するためだけに`nginx`を使っていて、設定ファイルの内容とかをほとんど知らない。
なので、ここに`nginx`の設定内容をまとめる事で自分自身が覚えようと思う。

普段使う大抵の設定は記載しているつもりです。

記載内容は実際に試したものと試してないものが混在してるので、誤った設定などがあるかもしれないのでその辺はコメントでご指摘いただけると助かります。

## インストール
インストールについては僕が書くより他の人の記事を見た方がいいと思う。
`centos`に入れるなら以下の記事が参考になる。

* [CentOS6.xにてnginxの最新版をインストールする手順](http://qiita.com/utano320/items/0c0d9b84a9a28525bcb9)
* [CentOS 6.5でnginxを動かす為の最低限の設定](http://qiita.com/ksworks/items/cbc7b73c62c5e115d830)

また`chef`でインストールする場合は以下の記事が役にたつ。

* [Chefでnginxを導入してみる](http://xoyip.hatenablog.com/entry/2013/04/16/140000)
* [ChefでNginxをインストールするときにハマった](http://qiita.com/rtbt525/items/7072357e6b32c9398869)

`chef`の使い方に関しては[僕の記事](http://qiita.com/syou007/items/469286077d2b6561720f)を参考にしてもらえれば幸いです。

### コマンド
以下のコマンドが使える。

```
$ /etc/init.d/nginx -h
Usage: nginx {start|stop|restart|condrestart|try-restart|force-reload|upgrade|reload|status|help|configtest}
```

#### 起動
とりあえず、起動コマンドだけ書いておく。

```
$ /etc/init.d/nginx start
# もしくは
$ service nginx start
```

## 設定ファイル
インストール後`/etc/nginx/nginx.conf`にnginxの設定ファイルが配置されている。
今回はこちらのファイルに定義できる事をまとめてみる。（メモってみる。）

### `user`
```
user nginx;
```

`nginx`を起動すると`master process`と`worker process`、`cache manager process`の三つのプロセスが起動します。
その中の`master process`以外を起動するユーザーを指定します。
`master process`は`root`ユーザーで起動します。

### `worker_processes`
```
worker_processes auto
worker_processes 2
```

Nginxがシングルスレッドで動作するため、コア数に合わせて設定しておく。
コア数よりも多くの値を指定しても問題がないらしい。
`auto`に指定するとコア数を設定してくれる。

なお、コア数は以下のコマンドで調べれる。

```sh
$ grep processor /proc/cpuinfo |wc
```

CPUの割り当てを明示的に使用する場合は以下を使用する。

```
worker_cpu_affinity 01 11
```

参考URL:
[Nginxのworker_processesとworker_cpu_affinity](http://setting-tool.net/worker_processes-worker_cpu_affinity)

### `worker_rlimit_nofile`
```
worker_rlimit_nofile  4096;
```
プロセス毎のファイルディスクリプタ上限数。
後述する`worker_connections`の3〜4倍くらいが目安になる。

なお、システムのファイルディスクリプタは以下のコマンドで確認が取れる。

```sh
$ cat /proc/sys/fs/file-max
```

参考URL:
[nginx で Too many open files エラーに対処する](http://www.1x1.jp/blog/2013/02/nginx_too_many_open_files_error.html)

### `error_log`
```
error_log /var/log/nginx/error.log;
```

nginxは動いたけどrailsまで届いてないみたい・・・などの時に真っ先にみるログの場所ですw（もしくは`access_log`。後述)
デフォルトのままで良いかと思います。

この定義はhttpやserverブロックなどでも使用できます。

### `pid`
```
pid /var/run/nginx.pid;
```

このファイルの中身をあまり見ることはないですが、PIDが格納されている。
ついつい以下のコマンドで確認してしまう・・・。

```
$ ps aux | grep nginx
root     31866  0.0  0.0  65724   276 ?        Ss   09:55   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    31868  0.0  0.2  67040  1544 ?        S    09:55   0:00 nginx: worker process                   
nginx    31869  0.0  0.0  65944   336 ?        S    09:55   0:00 nginx: cache manager process
```

## `events`ブロック
```
events {
	...
}
```

eventモジュールの定義ができます。
以下の三つの項目が`...`の中に記載できます。

### `worker_connections`
```
worker_connections 512;
```
一つのワーカーが同時に処理できる接続数です。

### `multi_accept`
```
multi_accept on;
```
`on`の場合、複数の接続をすべて1度に受け入れる。

### `use`
```
use epoll
```
「Linuxカーネル2.6以上の場合はepoll、BSDの場合kqueue」とのこと。通常は上記の設定で問題ないと思う。

## `http`ブロック
```
http {
	...
}
```

Webサーバーとして使用するメインとなる処理。

### `server_tokens`
```
server_tokens off;
```

エラーページのフッタに Nginx のバージョンを表示するかどうかの設定。
セキュリティ上`off`の方が望ましい。

### `include       /etc/nginx/mime.types;`
```
include       /etc/nginx/mime.types;
```

MIMEタイプと拡張子の関連付けを定義したファイルを読み込みます。

```
types {
    text/html                             html htm shtml;
    text/css                              css;
    text/xml                              xml;
    image/gif                             gif;
    image/jpeg                            jpeg jpg;
    application/javascript                js;
    ...
}
```

このような形で、MIMEタイプがまとめられてます。


### `default_type`
```
default_type  application/octet-stream;
```
上述のmime.typesで拡張子からMIMEタイプを決定できなかったときに、ここで指定したMIMEタイプが適応されます。
デフォルトの設定値はtext/plainです。

### `log_format`
```
log_format main 'time:$time_iso8601\t'...
log_format ltsv 'time:$time_iso8601\t'...
```

ログのフォーマットを定義します。`main`や`ltsv`などが選択でき、その後に出力したい値を定義します。
ここで定義したものを使用することができます。

参考URL:

* [nginxのログをLTSV形式で出力して、fluentd経由でMongoDBに保存する](http://qiita.com/key/items/038b7913b3bb0298c625)
* [LTSV FAQ - LTSV って何? どういうところが良いの?](http://d.hatena.ne.jp/naoya/20130209/1360381374)

### `access_log`
```
access_log /var/log/nginx/access.log ltsv;
```

上記で指定した`log_format`を最後に指定します。

この定義はserverブロックなどでも使用できます。

```
access_log off;
```

と設定することもできます。

### `charset`
```
charset UTF-8;
```

レスポンスヘッダーに`Content-Type: text/html; charset=UTF-8`などの`charset`を付与する。

### `sendfile`
```
sendfile on;
```

OSが提供している`sendfile`を使用するかどうかを指定します。
`sendfile`を使用すると`nginx`内部でファイルの読み込みと送信を行わず`カーネル空間内`で行ってくれるため効率良くファイルを送信できます。(jsファイルやcssファイルの転送に使用？）
デフォルトの設定値は`off`です。

### `tcp_nopush`
```
tcp_nopush on;
```

`sendfile`が`on`の時にこちらの設定を`on`にすると、レスポンスヘッダとファイルの内容をまとめて送るようになります。少ないパケット数で効率良く送ることができます。

### `tcp_nodelay`
```
tcp_nodelay on;
```

こちらは小さなパケットを待つことなく、そのまま送信するオプションです。待ちがないので早くなりますが、パケット数と送信量が増えます。
デフォルトは`on`です。
`tcp_nopush`と反対の動きをするそうですが、nginxはこの二つを組み合わせてもうまく動作するように実装されているようです。

うまく動かない場合は`sendfile`、`tcp_nopush`、`tcp_nodelay`を全て`off`にするとうまく動く場合があります。

### `keepalive_timeout`
```
keepalive_timeout 75;
```

HTTPの持続的な接続時間です。あまり長くするとコネクションを張りっぱなしになるスレッドが増えます。
0にすると`off`になります。
デフォルト`75`。

### `keepalive_requests`
```
keepalive_requests 100;
```

`keepalive_timeout`が有効な時に同じクライアントからの要求が指定の数に達するとコネクションを切断します。
通常に使うなら`keepalive_timeout 5`と`keepalive_requests 20`くらいで十分な気がする。
デフォルト`100`。

### `set_real_ip_from`と`real_ip_header`
```
set_real_ip_from   10.0.0.0/8;
real_ip_header     X-Forwarded-For;
```

`Proxy`や`ロードバランサー`を経由した時に元のIPアドレスが失われてしまうことを防ぎます。
`set_real_ip_from`で`Proxy`や`ロードバランサー`を指定して、`Proxy`や`ロードバランサー`が保持している`正しいIPアドレス`が記載されている`ヘッダーパラメータ`を`real_ip_header`に指定します。
`X-Forwarded-For`が通例ですが、上位サーバーに依存するので上手くIPアドレスが取得できない場合は確認すること。

`set_real_ip_from`は複数記載可能。

### `client_header_timeout`と`client_body_timeout `
```
client_header_timeout 10;
client_body_timeout 10;
```

クライアントのリクエストヘッダとクライアントリクエストボディの読み込みのタイムアウト時間。

### `client_body_buffer_size `と`client_body_temp_path`
```
client_body_buffer_size      32k;
client_body_temp_path /dev/shm/client_body_temp 1 2;
```

受け付けたリクエストのボディは`client_body_buffer_size`まではメモリで保持し、それ以上は`client_body_temp_path`へファイルとして吐き出します。

[nginxのリクエストボディのバッファリングに関する問題とその改善策](http://qiita.com/cubicdaiya/items/0678396f11982e537e2d)に書かれてますが`client_body_buffer_size`が定義されていても以下のように`server`ブロックに`proxy_request_buffering off`を指定すればその条件ではバッファリングされなくなります。

```
server {
    listen 80;
    server_name example.com;

    location /upload {
        proxy_request_buffering off;
        proxy_pass http://upload_backend;
    }
}
```

### `client_max_body_size`
```
client_max_body_size 1m;
```

クライアントから送られてくるボディのマックス値です。これ以上のサイズが送られてくると`413(Request Entity Too Large)エラー`が発生します。

### `client_header_buffer_size`と`large_client_header_buffers`
```
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
```

通常は気にしなくてOK。
この定義を超えるヘッダーを送られた場合は`414 (Request-URI Too Large) エラー`が発生します。

### `limit_conn`、`limit_conn_zone`
```
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn  addr  100;
```

同時接続数を制限します。
Dos攻撃等を防ぎたい方は以下のサイトが参考になります。

参考URL:
[Nginxで使える制限一覧](http://shinobra.com/2012/03/sawanoboly/nginx_limiter)

### proxy関連
```
proxy_buffering on;
proxy_buffer_size     8k;
proxy_buffers         100 8k;
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=CACHE:512m inactive=1d  max_size=60g;
```

リバースプロキシとして使用する場合の設定です。
この辺りは僕の理解を超えてます・・・。（`unicorn`を使う場合はここの設定をしっかり設定する必要がある気がするけど・・・。）
[Nginx をリバースプロキシ(キャッシュ) として使ってみた](http://server-setting.info/centos/apache-nginx-10-proxy.html)が参考になるかと思います。

### gzip関連
```
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied expired no-cache no-store private auth;
gzip_vary off;
gzip_types text/plain
       text/css
       text/xml
       ...
       application/json;
gzip_min_length 1000;
gzip_disable "MSIE [1-6]\.";
```

レスポンスに`gzip`を使用する場合に`on`にします。サーバー間の転送量を抑えることができます。

以下、実際に使う時に変更するものだけを軽く記載。
`gzip_types`で指定しているタイプのファイルのみが有効になります。
`gzip_proxied`で指定しているリクエストタイプに対してのみ有効になります。
`gzip_min_length`よりも少ないレスポンスはgzip化しません。圧縮コストの方が高くなってしまいます。
`gzip_disable`、、、とりあえずIE6以下はgzip対象外にしましょう。

### `open_file_cache`関連
```
open_file_cache max=100 inactive=10s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
```

[nginxパフォーマンスチューニング〜静的コンテンツ配信編〜](http://qiita.com/cubicdaiya/items/2763ba2240476ab1d9dd)が参考になります。

ファイルディスクリプタやサイズ、更新時間といった情報をキャッシュすることができます。

### `server_names_hash_bucket_size`
```
server_names_hash_bucket_size 64
```

とりあえず64を指定しておけばいい気がします。
[nginxのエラー“increase server_names_hash_bucket_size”の対処方法](http://webkaru.net/linux/nginx-error-increase-server-names-hash/)

### `types_hash_max_size`
```
types_hash_max_size 1024;
```

タイプのハッシュテーブルのsizeの最大値を設定します。 

### `types_hash_bucket_size`
```
types_hash_bucket_size 64;
```

タイプのハッシュテーブルのためのbucketサイズを設定します。
この辺はデフォルト値でいい気がする。

### `listen`
```
listen 80 default_server;
```

nginxをそのまま使う場合は`http`ブロック内に記載しますが、通常はバーチャルホストで使用すると思うのでここに記載することはあまりないと思う。
なお`default_server`をつければマッチしない場合に使われる。

### `server_name_in_redirect`
```
server_name_in_redirect off;
```

リダイレクト時にサーバー名をヘッダーに埋め込むかどうかですが、`on`にすることは基本的にないと思います。
`off`にすればクライアントがリクエストしてきたHostヘッダの文字列がLocationのホスト名に使われます。

### `port_in_redirect`
```
port_in_redirect on;
```

`on`ならリダイレクト時、URL の末尾にポート番号を付与する。

### `upstream`
```
upstream unicorn {
  server unix:/path/current/tmp/sockets/unicorn.sock fail_timeout=0;
}

upstream server_com {
      server 127.0.0.3:8000 weight=5;
      server 127.0.0.3:8001 weight=5;
      server 192.168.0.1:8000;
      server 192.168.0.1:8001;
}

server {
  listen 80;
  server_name unicorn;

  root /path/current/public;
  
  location @unicorn {
　　　proxy_set_header X-Real-IP $remote_addr;
　　　proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
　　　proxy_set_header Host $http_host;
    proxy_pass http://unicorn;
  }
}

server {
      listen          80;
      server_name     server.com;

      location / {
        proxy_pass      http://server_com;
      }
}
```

`unicorn`などのバックエンドサーバーを使用する時に`upstream`で`socket`を指定する。（僕は`pid`を指定してしまい動かなかったという超恥ずかしい事をした事がある・・・。）

また、他のサーバーを複数指定してロードバランスする事もできる。

### `proxy_set_header`等
```
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header X-Powered-By;
proxy_ignore_headers Expires;
```

バックエンドサーバに送信するヘッダを定義し直す。
大体上記の設定で問題ないと思う。

リバースプロキシを使う場合は`proxy_pass`は先に定義する必要がある。
[nginxのproxy_set_headerの設定場所](http://og732.hatenadiary.com/entry/2013/05/20/202548)

※Unicornなどのソケット通信の場合は`proxy_pass`を後ろに書いても問題ないっぽい。

`proxy_hide_header`はヘッダー情報を消します。セキュリティ上クライアントに漏らしたくない情報を消します。

`proxy_ignore_headers`で指定した値は無視する。上記の例では`Expires`を無視するのでキャッシュされない・・・。（よくわかってない）

```
proxy_connect_timeout
proxy_send_timeout
proxy_read_timeout
```

などの設定もあります。
詳しくは[お名前.com VPS にNginxでWordPressを構築。設定の意味もまとめた](http://www.karakaram.com/onamae-com-vps10-nginx-wordpress)がわかりやすかったです。

と思ったのですが、この設定は結構重要なので簡単に説明しておきます。
`nginx`に設定されている`upstream server`が`unicorn(Rails)`だとした場合を例に説明します。

#### proxy_connect_timeout
`nginx`から`unicorn`へコネクションを張るタイムアウト時間です。
通常は１秒とかでコネクションは張られるはずです。
最大75秒ですが、10秒とかの設定で十分だと思います。

#### proxy_send_timeout
`nginx`から`unicorn`に対してデータを送信する際のタイムアウト値です。
送信で時間がかかることは無いので、これも10秒とかの設定で十分だと思います。
（どんなに大きなファイルを送信してもHTTPリクエストで考えると数秒で終わると思います。）

#### proxy_read_timeout
この値が一番重要です。
渡されたファイル（データ）をもとに`unicorn`が処理をすると思いますが、この値の設定を過ぎるをコネクションが切られてしまいます。
なので`unicorn`に処理をさせる場合に想定される最大時間を設定します。
（[巨大CSVの処理](http://qiita.com/syou007/items/a61fa1001027fad28b4a)のように時間が掛かる場合はこの値を長めにとっておきましょう！）

また、`unicorn`にもタイムアウトの設定がありますので`unicorn`のタイムアウトよりも長い時間設定しておく必要があります。

### `proxy_redirect`
```
proxy_redirect off;
```

バックエンドサーバがリダイレクトした時の Location ヘッダ。on なら proxy_pass をホスト名としてリダイレクト。off ならサーバの指示通りにリダイレクト。

### `error_page`、`proxy_intercept_errors`
```
proxy_intercept_errors on;
error_page 404             /404.html;
error_page 403 =404 /notfound.html; # 403の場合404に変換される。
error_page 500 502 503 504 /50x.html;
```

エラーステータスに応じたページを表示します。

`server`や`location`ブロックでも使用できます。

`proxy_intercept_errors`を`on`にする必要があります。

### `include /etc/nginx/vhost.d/*.conf;`
```
include /etc/nginx/vhost.d/*.conf;
```

serverなどを別のファイルに定義する場合は上記の設定を行います。
これによって指定フォルダのファイルが読み込まれます。
(httpブロックに記述すれば、httpブロックに展開されるっぽいので個別ファイル内では`http{}`を記述する必要はない。）

## `server`ブロック
```
http {
	server {
		...
	}
}
```

nginxでバーチャルホストの運用をする際に使用します。
serverで区切った単位でバーチャルホストが作成されます。

`http`ブロック内に記述します。

`server`ブロック内の記述は大体`location`でも使用できます。
（`listen`,`server_name`,`root`は使用できない。）

### `listen`と`server_name`
```
listen 80 default_server;
server_name localhost;
```

このバーチャルホストにアクセスするための情報です。
`listen`はIPアドレスなども指定できますが、僕はポート番号しか指定した事がありません。
`default_server`を指定すると他の全てにマッチしない場合に使われるサーバーになります。
また、`listen`には様々なオプションがあるようです。[こちら](http://mogile.web.fc2.com/nginx/http/ngx_http_core_module.html#listen)を参照ください。

`server_name`は指定のドメインの場合に対象となります。
このケースでは`http://localhost:80`の場合に適用されます。

### `root`
```
root /path/public
```

このserverブロック内で使用するルートディレクトリを指定します。

### `rewrite`
```
rewrite /(.*)/index.html $1.html permanent;
```

リダイレクトさせたい場合に使用します。

### `satisfy`,`auth_basic`
```
satisfy any;
auth_basic "basic authentication";
auth_basic_user_file /etc/nginx/.htpasswd;
```

`satisfy`は一部のアドレスにBasic認証をかけない場合などに使います。[こちらのサイト](http://d.hatena.ne.jp/podhmo/20110311/1299817584)がわかりやすかったです。
`auth_basic`は認証名を表示させます。
`auth_basic_user_file`にパスワードファイルを指定します。

### `try_files`
```
try_files $uri $uri.html $uri/index.html @unicorn;
```

指定のファイルが存在するかを左から探しに行きます。
例えば`http://***/hoge`でアクセスした場合は`hoge.html`、`hoge/index.html`、`location @unicorn {}`の順番に探します。

## `location`ブロック
```
http {
	server {
		location / {
			...
		}
	}
}
```

指定のロケーション（パスやファイル）の場合に適用されます。

以下のように正規表現で指定することもできます。

```
location ~ /\.(ht|svn|git) {
	deny all;
}
```

上記の設定は`.htaccess`や`.svn`、`.git`などのファイルにアクセスさせたくない場合に使用します。

### `stub_status`や`allow`、`deny `
```
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
```

`stub_status`が指定されたロケーションにアクセスすると`現在の接続数`などの情報がみれます。
通常外に公開する事はありません。

`allow`を指定した場合は`対象のIP`からのアクセスを許可します。ここでは`127.0.0.1`を許可してます。

`deny`を指定した場合は`対象のIP`からのアクセスを禁止します。ここでは全てのアクセスを禁止してます。

`nginx`は上から評価されるため、上記のケースの場合は`allow 127.0.0.1`が先に評価されるため`127.0.0.1`のアクセスのみが適用されます。

もし、以下のように逆に記述してしまうと全てのIPアドレスからのアクセスが拒否されます。（Apacheとは違うので注意。）

```
deny all;
allow 127.0.0.1;
```

なお`allow`や`deny`に関して`ドメイン名`が使えるかどうかの記事は見当たらなかったため分かりませんでした。ただ、`ドメイン名`を指定すると`DNSサーバー`へアクセスして判断する必要が出てくるはずなので基本的には行わないと思います。

### `expires`
```
expires 10d;
```

ブラウザキャッシュを使用する場合に使用する。上記の例だと10日はブラウザのキャッシュを使用する。

### `add_header`
```
add_header Cache-Control public;
```

レスポンスヘッダーにつける値を設定します。
以下のURLが参考になります。

* [nginx を知る:: 後編](http://pydiary.bitbucket.org/blog/html/2014/02/01/nginx.html)
* [HTTP キャッシュ ヘッダの設定 - Cache-Control](http://otndnld.oracle.co.jp/document/products/E13158_01/alui/wci/docs103/devguide/tsk_pagelets_settingcaching_httpcachecontrol.html)

### `break`
```
break;
```

これ以降のrewrite処理を行わない。

参考URL:
[nginx rewriteのlastとbreakの違い](https://siguniang.wordpress.com/2014/02/16/nginx-url-rewriting-difference-between-break-and-last/)

### `internal`
```
error_page 404 /404.html;

location /404.html {
    internal;
}
```

内部リダイレクトにしか使いたくない場合に使用します。
この例では、直接`/404.html`ページを見ることができません。

## 参考URL:
* [nginx最大パフォーマンスを出すための基本設定](http://nodejs.osser.jp/server/nginx-max-performance/)
* [お名前.com VPS にNginxでWordPressを構築。設定の意味もまとめた](http://www.karakaram.com/onamae-com-vps10-nginx-wordpress)
* [nginx連載3回目: nginxの設定、その1](http://heartbeats.jp/hbblog/2012/02/nginx03.html)
* [nginxのパラメータチューニングとh2o](http://qiita.com/cubicdaiya/items/235777dc401ec419b14e)
* [LaravelとNginxの快速仕立て、キャッシュを添えないで…](http://kore1server.com/287/Laravel%E3%81%A8Nginx%E3%81%AE%E5%BF%AB%E9%80%9F%E4%BB%95%E7%AB%8B%E3%81%A6%E3%80%81%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E6%B7%BB%E3%81%88%E3%81%AA%E3%81%84%E3%81%A7%E2%80%A6)
* [nginx でKeepAliveを設定してみる](http://server-setting.info/centos/nginx-keepalive-setting.html)
* [Nginx で Elastic Load Balancing などの Proxy の内側で正しい IP アドレスを取得する](http://d.hatena.ne.jp/Craftworks/20101204/1291426738)
* [nginxのリクエストボディのバッファリングに関する問題とその改善策](http://qiita.com/cubicdaiya/items/0678396f11982e537e2d)
* [nginxパフォーマンスチューニング〜静的コンテンツ配信編〜](http://qiita.com/cubicdaiya/items/2763ba2240476ab1d9dd)
* [ngx_http_core_module モジュール](http://mogile.web.fc2.com/nginx/http/ngx_http_core_module.html)
* [ngx_http_proxy_module モジュール](http://mogile.web.fc2.com/nginx/http/ngx_http_proxy_module.html)
* [ngx_http_gzip_module モジュール](http://mogile.web.fc2.com/nginx/http/ngx_http_gzip_module.html)