(今更)Nginx覚書

ブログやってます。更新などはこちら。[地方エンジニアの学習日記](https://ryuichi1208.hateblo.jp/)

![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258841/8455d002-5d59-d6f0-d99b-b6f113998716.png)

[関連サイト]

* https://nginx.org/
* https://github.com/nginx/nginx
* https://www.nginx.com/

## 背景

リバースプロキシなどなど学習ついでに得た知見のメモ書き
インストール方法等は記載してません。

## Nginxコマンドと設定ファイル

``` bash:コマンド
# 起動
$ nginx

# 停止
$ nginx -s stop

# 設定ファイル再読み込み
$ nginx -s reload

# 設定ファイルのシンタックスチェック
$ nginx -t 

# ヘルプを表示
$ nginx -h
nginx version: nginx/1.17.3
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /etc/nginx/)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

# バージョンを表示
$ nginx -v
nginx version: nginx/1.17.3
```

``` bash:設定ファイル
# メイン設定ファイル
/etc/nginx/nginx.conf

# 各サーバー用設定ファイル
# (下記はインストール時のデフォルトのserverの設定ファイル)
/etc/nginx/nginx.d/default.conf	
```

## Nginx設定

#### 設定ファイルの概要

``` nginx
設定項目A 設定値1;
設定項目B 設定値2;

events {
    設定項目C  設定値3;
}

http {
    server {
        設定項目D  設定値4;

        location 設定値5 {
            設定項目E 設定値6;
        }
    }
}
```

#### 基本ディレクティブ

ディレクティブの書式には以下の2種類があります。
・ディレクティブ名 値;
・ディレクティブ名 値 {}

``` nginx
# user user [group];
# workerプロセスを実行するユーザーとグループを指定
user root

# worker_processes [num];
# ワーカープロセス数を指定します。(autoとすることでCPUのコア数を自動割り当て)
worker_processes auto;

# worker_rlimit_nofile [num]
# nginxのワーカープロセスのFD数の上限を指定
worker_rlimit_nofile 2048;

# error_logfile [level];
# nginxサーバのログファイルの設定
error_log /var/log/nginx/error.log warn;

# pid file
# nginxのmainプロセスのプロセスIDを格納するファイル
pid /var/run/nginx.pid;

# events {...}
# 接続処理を指定するディレクティブが設定された構成ファイルを提供
events {
    worker_connections  1024;
}

# include file | mask ;
# 指定されたファイルまたは指定されたマスクと一致する別のファイルを構成に含める
include /etc/nginx/conf.d/*.conf;

# load_module file;
# 指定した動的モジュール(file)をモジュールとしてロード
load_module modules/ngx_mail_module.so;

```

#### serverコンテキスト内

serverコンテキストはバーチャルホストに関する設定を記述します。serverコンテキストはhttpコンテキスト内に各バーチャルホストごとに記述します。

参考
* [Contextを制するの者はnginxを制する!!](https://qiita.com/sakajunquality/items/04325532f67312a99ad9)

``` nginx
    server {
        # 使用するIPアドレス、ポートを指定
        # default_serverオプションをつけると、それがデフォルトサーバーとして扱われる
        listen       80 default_server;

        # ドキュメントルートを指定
        root         /usr/share/nginx/html;

        # 任意のURI毎に異なる設定をする
        # リクエストURIのパスがこのlocationディレクティブのパスの条件に
        # 一致した場合にこのlocationコンテキストに記述した設定が適応され
        location / {
        }

        # 404の時のエラーページを指定する
        error_page 404 /404.html;
            location = /40x.html {
        }
 
        # ステータスコードを複数割り当てることも可能
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
```

#### 変数

設定ファイルで使えるよく見る変数の表です。
詳細/その他変数は公式ドキュメントをご参照ください。

* [Module ngx_http_core_module](http://nginx.org/en/docs/http/ngx_http_core_module.html)

変数名|説明
-----|---
$args|GETパラメータ
$document_root|設定されてるドキュメントルート
$host|アクセスされたURLのホスト名
$remote_addr | アクセス元のIPアドレス
$remote_port | アクセス元のポート番号
$remote_user | Basic認証で提供されたユーザ名
$request | 完全なオリジナルリクエスト行
$request_method | リクエストのメソッド。「GET」や「POST」などの値
$request_uri | アクセスされたuri情報
$scheme | リクエストのスキーム。「http」や 「http」などが格納されます
$server_addr | リクエストを受け付けたサーバのIPアドレス
$server_name | リクエストを受け付けたサーバの名前
$server_port | リクエストを受け付けたサーバのポート番号
$status | レスポンスステータス
$http_referer | アクセス元がどこから来たのか
$http_user_agent | アクセス元のユーザエージェント

#### リダイレクト : rewrite

rewrite文を書くことでリダイレクトできる

``` nginx
# 基本
# regex : 正規表現でのマッチパターン
# replacement : マッチパターンに一致した場合の変換パターン
# flag : リダイレクトフラグ
rewrite regex replacement [flag];

# 正規表現
# なし ： 前方一致
# ^~   ： 前方一致。正規表現よりも優先。
# =    ： 完全一致
# ~    ： 正規表現(小文字・大文字を区別)
# ~*   ： 正規表現(小文字・大文字を区別しない)
```

フラグ名|説明
------|---
LAST|rewrite処理を停止し、書き換えられたURIに対してlocationを再検索
BREAK|rewrite処理の停止し、locationの検索を停止
PERMANENT|恒久的なリダイレクト(ステータスコード301)
REDIRECT|一時的なリダイレクト(ステータスコード302)

#### リバースプロキシ関連

``` nginx:default.con
server{
    server_name    web.com;

    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;

    # X-Fowarded-Host : クライアントがHostヘッダを渡すオリジナルのホスト名
    proxy_set_header    X-Forwarded-Host       $host;

    # X-Forwarded-Server : プロキシサーバのホスト名
    proxy_set_header    X-Forwarded-Server    $host;

    # X-Forwarded-For : クライアントのIPアドレス
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;

    location /api/v1/users {
        proxy_pass    http://web_old.com;
    }

    location /api/v2/users {
        proxy_pass    http://web_new.com;
    }
}
```

簡単に上の設定を解説します。
```proxy_pass```ディレクティブは```location```にきたリクエストを指定したサーバへ転送することができます。
```proxy_set_header```はプロキシサーバに送られるリクエストヘッダのフィールドを追加/再定義します。

``` nginx:書式
proxy_set_header  field  value;
```

value には、値やテキスト、変数、あるいはそれらの 組み合わせが指定可能です。
現在のコンテキストにそのディレクティブがない時は上位のコンテキストで設定された値が継承されます。

* [nginxでproxy_hide_header, proxy_set_header, add_headerを書く時にはまりがちな罠](https://dekotech.dekokun.info/entry/2016/03/10/184304)

また、開発用途で使用しているサーバ自身の状況をレスポンスにセットしている場合にリバースプロキシで情報を落とすこともできる。

``` nginx
server {
  proxy_hide_header X-hoge;
  proxy_hide_header X-fuga;
}
```

#### ロードバランサ

Nginxにはロードバランサの機能もあります。使用できる方法は3パターンあります。

* ラウンドロビン (デフォルト)
 * 重み付きのラウンドロビン
* Least Connected
 * 送信先サーバは、アクティブな接続とserverの重みが考慮された数がもっとも少ないサーバへ決定
* IPハッシュ
 * 送信先サーバは、クライアントのIPアドレスで決定

upstreamモジュールを利用することで、プロキシサーバー群を定義することができるようになります。
upstreamディレクティブはhttp コンテキストに配置されます。

``` nginx
upstream backend {
    # least_conn;
    # ip_hash;

    # weightを設定することでリクエストは「3:1:1」となる
    server webapp1.com weight=3;
    server webapp2.com;
    server webapp3.com;
}
```

上記は単純に指定したサーバへリクエストを振り分けているだけのためダウンしているサーバへもリクエストは飛ぶ
Nginxでダウンしたサーバを検知してリクエストを飛ばさないようにする仕組みもあります。それが```Health Checks```です。

``` nginx
upstream backend {

    server webapp1.com weight=3 max_fails=100 fail_timeout=10;;
    server webapp2.com max_fails=100 fail_timeout=10;;
    server webapp3.com max_fails=100 fail_timeout=10;;
}
```

### SSLオフロード

SSLの代理処理をする「SSLアクセラレータ(SSLオフロード)」

* [SSLとTLSの違いとは](https://ssl.sakura.ad.jp/column/ssl_tls/)

``` nginx
# http でアクセスしてきた場合は https にリダイレクト
server {
    listen 80;
    server_name hoge.com;
    return 301 https://$host$request_uri;
}

server {
    listen       443 ssl ;
    server_name  hoge.com;
 
    ssl_protocols       TLSv1.1 TLSv1.2;
    ssl_certificate     /etc/pki/tls/certs/hoge.crt;
    ssl_certificate_key /etc/pki/tls/private/hoge.key;;
 
    # プロキシ先の指定とApacheに渡すリクエストヘッダーの指定
    location / {
        proxy_pass https://fuga.com:8080;
        proxy_redirect                         off;
        proxy_set_header Host                  $host;
        proxy_set_header X-Real-IP             $remote_addr;
        proxy_set_header X-Forwarded-Host      $host;
        proxy_set_header X-Forwarded-Server    $host;
        proxy_set_header X-Forwarded-For       $proxy_add_x_forwarded_for;

        # バックエンドサーバの証明書も確認する(デフォルトOFF)
        proxy_ssl_verify on;
        proxy_ssl_trusted_certificate /etc/pki/tls/certs/fuga.crt;
    }
}
```

参考
* [HTTP Health Checks](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/)
* [nginx upstream パッシブヘルスチェックはかなり使える (max_fails, fail_timeout)](http://neinvalli.hatenablog.com/entry/2017/10/31/002839)

### プロキシキャッシュ

proxyキャッシュを設定することもできる。
この節はNginx のリバースプロキシでファイルをキャッシュする方法です。

``` nginx
    proxy_cache_path /var/cache/nginx keys_zone=zone1:1m max_size=1g inactive=24h;
    proxy_temp_path  /var/cache/nginx_tmp;
```

proxy_cache_pathにはキャッシュ保存場所を指定する。
proxy_temp_pathにはキャッシュ用の一時ファイルの置き場所。

## 参考サイト

* [IT生涯学習Tech nginx](https://gakumon.tech/nginx/index.html)
* [Nginx設定のまとめ](https://qiita.com/syou007/items/3e2d410bbe65a364b603)
* [remote_addrとかx-forwarded-forとかx-real-ipとか](https://christina04.hatenablog.com/entry/2016/10/25/190000)
* [NGINX ロードバランス](http://mogile.web.fc2.com/nginx/admin-guide/load-balancer.html)