nginxはロシアのIgor Sysoev氏によって開発されているHTTPサーバ兼リバースProxyのソフトウェアであり、「エンジン エックス」(engine x)と発音する。apacheと違い、リクエストに対してスレッドを起動しない為、メモリやCPUのオーバーヘッドが極力まで抑えられており、大量のリクエストを幅くことができる。反面、1つのリクエストが無限ループに入ると、システム全体が停止する。そのため、主にサーバー群のフロントサーバーとして、リバースプロキシ+静的コンテンツのhttpサーバー(画像や静的なページなど)として利用するのが適切である。(要するに確実に停止しない処理で膨大なリクエストを捌く必要があるものを担当させる) 公式ページ
下記のライブラリが必要となるため、先にインストールしておく必要がある。
<初期準備>
# yum install pcre-devel zlib-devel expat-devel
<dav extを利用する場合>
# cd /usr/local/src # git clone https://github.com/arut/nginx-dav-ext-module
※但し、nginx ではWebDavとしての機能は十分でなく参照のみ機能
<Luaを利用する場合>
# cd /usr/local/src # git clone https://github.com/openresty/lua-nginx-module
<安定版>※オプションで不必要なものは外してください。
# wget http://nginx.org/download/nginx-1.16.1.tar.gz # tar zxvf nginx-1.16.1.tar.gz # cd nginx-1.16.1 # ./configure --with-http_ssl_module --with-openssl=/usr/local/src/openssl-1.0.2n --with-http_gzip_static_module --with-http_stub_status_module --with-http_dav_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_addition_module --with-cc-opt=-Wno-error --with-ld-opt= --add-module=/usr/local/lib/ruby/gems/2.4.0/gems/passenger-5.1.11/src/nginx_module --add-module=/usr/local/src/nginx-dav-ext-module --add-module=/usr/local/src/lua-nginx-module # make # make install
※1.5.10からは、Googleが提唱するHTTP速度向上プロトコルSPDYに対応している。
※opensslのパス指定はインストールフォルダではなく、ソースフォルダを指定する。
※ほかのオプションはここが参考になる。
<Passenger付き>
# gem install passenger # passenger-install-nginx-module <- configureはここで行われるため下の行は参考 # ./configure --prefix='/usr/local/nginx' --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_addition_module --with-cc-opt=-Wno-error --with-ld-opt='' --add-module='/usr/local/lib/ruby/gems/2.2.0/gems/passenger-5.1.3/src/nginx_module
nginxのキャッシュクリア方法には、「時間経過による削除」と「全削除」の2種類しかないため、キャッシュクリアのモジュールを追加するため以下もインストールする。
# cd <nginxのフォルダ> # mkdir srclib # cd srclib # wget http://labs.frickle.com/files/ngx_cache_purge-2.1.tar.gz # tar zxvf ngx_cache_purge-2.1.tar.gz # ./configure --with-http_ssl_module --add-module=srclib/ngx_cache_purge-2.1
pagespeedは元は apache用でgoogleによって作られたものであるが、現在 nginx用にも存在する。機能としては以下のとおり。(詳細は公式サイトを参照のこと)
※インストールは、公式サイトから git や zip でダウンロードし、ngx_cache_purgeと同じ方法でモジュール追加する。
設定のサンプルページ
nginxの現在の接続数などを表示するモジュール。nginx をコンパイルする時に指定。
--with-http_stub_status_module
nginx.conf 内では、locationディレクティブで指定
location /status { stub_status on; }
これによって該当ページに接続情報が表示される。
Active connections: 1 <- 現在の接続数 server accepts handled requests 5 5 4 <- 受け付けた接続総数, 制御した接続総数, 制御した要求総数 Reading: 0 Writing: 1 Waiting: 0 <- リクエストヘッダー読込中, リクエストボディの処理中, keep-alive接続数
オプション名(例付き) | 概要 |
--user=nginx | プロセスのユーザーを指定 |
--group=nginx | プロセスのグループを指定 |
--with-http_ssl_module | SSLモジュールを追加 |
--with-http_realip_module | |
--with-http_addition_module | |
--with-http_xslt_module | |
--with-http_image_filter_module | |
--with-http_geoip_module | |
--with-http_sub_module | |
--with-http_dav_module | |
--with-http_flv_module | |
--with-http_mp4_module | |
--with-http_gzip_static_module | |
--with-http_random_index_module | |
--with-http_secure_link_module | |
--with-http_degradation_module | |
--with-http_stub_status_module | |
--prefix=/usr/local/nginx | nginxのインストール先を指定する |
--sbin-path=bin/nginx | 実行ファイルのインストール先を指定する |
--conf-path=conf/nginx.conf | 設定ファイルの指定をする |
--error-log-path=log/error.log | エラーログの指定をする |
--pid-path=/var/run/nginx.pid | pidファイルの指定をする |
--lock-path=/var/lock/subsys/nginx | ロックファイルの指定をする |
--http-log-path=log/access.log | アクセスログのファイルを指定する |
--add-module=srclib/ngx_cache_purge-2.1 | 指定のフォルダから追加モジュールをconfigureする |
stickeyディレクティブは、upstream モジュールによって、接続サーバーに複数のサーバーを指定し、ロードバランシングを行う際に、ステートフルな websocket 接続などの場合に、cookieを利用して自動的に同一接続であることを判定し、同じのサーバーに再接続させるためのものである。
現状、このディレクティブは追加モジュールとなっているので下記の手順で追加が必要となる。(下記操作は nginx のソースフォルダ内で実行)
# mkdir modules # cd modules # wget https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/f2adff04b8e3.zip # unzip f2adff04b8e3.zip # mv nginx-goodies-nginx-sticky-module-ng-f2adff04b8e3 sticky # rm -f f2adff04b8e3.zip
これでモジュール追加の準備ができたので、configure のオプションに下記を追加する。
--add-module=./modules/sticky
# mkdir modules # cd modules # wget https://github.com/openresty/lua-nginx-module/archive/master.zip # unzip master.zip # rm -f master.zip # mv lua-nginx-module-master lua
これでモジュール追加の準備ができたので、configure のオプションに下記を追加する。
--add-module=./modules/lua
※Luaは、LuaJIT2.0.3がおすすめ。また so ファイルのライブラリパスを /etc/ld.so.conf.d/に設置して、ldconfig を実行することを忘れないこと。
これは、pure Lua のライブラリなので、Lua のライブラリパスに設置すれば利用できます。
Redis v.1 の公式ページ
Redis v.2 の公式ページ1
Redis v.2 の公式ページ2
Redis1
# wget http://people.freebsd.org/~osa/ngx_http_redis-0.3.7.tar.gz
Redis2
# wget https://github.com/agentzh/redis2-nginx-module/archive/v0.11.tar.gz
参考2
location /redis { internal; set $redis_key $host; redis_pass 127.0.0.1:6379; } location /redis2 { internal; redis2_query get testkey; redis2_pass localhost:6379; }
※internal をつけると、内部からのみ呼び出し可能となる。
但し misc モジュールには、ngx_devel_kit が必要になる。
# wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz # wget https://github.com/openresty/set-misc-nginx-module/archive/v0.26.tar.gz
# nginx -V
ソースから導入した場合 | /usr/local/nginx/conf/nginx.conf |
パッケージから導入した場合 | /etc/nginx/nginx.conf |
設定ファイルは、apache に比べてば非常にシンプルとなっている。
設定項目名 | 初期値 | 概要 |
user | nobody | nginxが起動されるユーザー名 |
worker_processes | 1 | 実際に処理されるworkerの数を指定。通常は cpu の数以下を指定 |
error_log | logs/error.log notice | エラーログの出力先を指定。例のようにエラーレベル(noticeなど)を指定すれば対象ログ毎にファイルを分けることが可能。(複数行指定可能) |
pid | logs/nginx.pid | pidを保存するファイルを指定 |
events { } で囲われた部分がイベントに関する設定を行う。
設定項目名 | 初期値 | 概要 |
worker_connections | 1024 | 1つのworkerが接続できるクライアント数の上限を設定する |
http { } (以下、httpブロックと呼ぶ)で囲われた部分がhttpサーバーに関する設定を行う。
設定項目名 | 初期値 | 概要 |
include | mime.types | 他のファイルを読み込む |
default_type | application/octet-stream | |
log_format | main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' | |
access_log | logs/access.log main | |
sendfile | on | |
tcp_nopush | on | |
keepalive_timeout | 0 | |
gzip | on |
httpの中で、server{} と、複数のバーチャルサーバーの設定を行うことができる。通常ここは別ファイルにしておくとわかりやすい。
設定項目名 | 初期値 | 概要 |
listen | 80 | |
server_name | localhost | |
charset | koi8-r | |
access_log | logs/host.access.log main | |
error_page | 500 502 503 504 /50x.html | エラーページの設定。エラー番号別に記載可能(複数行指定可能) |
ssl | on | 【HTTPS用】ssl対応のon/off(SSL時必須) |
ssl | certificate cert.pem | 【HTTPS用】証明書ファイルの指定(SSL時必須) |
ssl_certificate_key | cert.key | 【HTTPS用】キーファイルの設定(SSL時必須) |
ssl_session_timeout | 5m | 【HTTPS用】セッションタイムアウトの時間 |
ssl_protocols | SSLv2 SSLv3 TLSv1 | 【HTTPS用】対応するプロトコルの種類を設定 |
ssl_ciphers | HIGH:!aNULL:!MD5 | 【HTTPS用】暗号化強度 |
ssl_prefer_server_ciphers | on | 【HTTPS用】 |
※sslのサーバーブロックで指定するサーバー名は、SSLのサーバ証明書で指定したCN(Common Name)と同じサーバ名を指定する事。
またサーバーブロックでは、それぞれの location 設定を下記のような指定で行うことができる。
location / { root html; index index.html index.htm; } location = /50x.html { root html; } location ~ \.php$ { proxy_pass http://127.0.0.1; } location ~ /\.ht { deny all; }
ssl_prefer_server_ciphers on; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AESGCM:RC4:HIGH:!MD5:!aNULL;
location構文はサーバーに到着したURIを解析し処理を振り分ける為の構文で、locaton の中に location を記述することもできる。
番号 | 記述例 | チェック方法 | 処理後 | 概要 |
1 | location = /path | 完全一致 | 終了 | この場合は、/path と完全合致する場合を意味し、合致した場合、その後の検索も終了するため、例えばルートをよく参照するようなサイトの場合に location = / のように、指定することで他の条件検索が無い分、処理が早くなる |
2 | location ^~ /path | 前方一致 | 終了 | これは /path* のような前方一致する場合を意味する。文字列として判断するため、フォルダの区切りも文字として判定される。これも上記と同じで他の検索をせず、その後の検索を行わない |
3 | location /path | 前方一致 | 継続 | 終了しても他を検索する以外2番と同じ |
4 | location ~ ^/path/(.*\.php)$ | 正規表現 | 継続 | "~" は大文字・小文字を区別する事を意味する。これが "~*" というようにアスタリスクが付くと、大文字・小文字を区別しないで正規表現での判定を行う |
※4番の正規表現解説:^を指定することで行の先頭からチェックを行う宣言をし、/path/ という文字が行の先頭から合致し、「 .* 」 の組み合わせで、改行を除く任意の1文字(ピリオド)を、0回以上の繰り返し(アスタリスク)チェック。その後ろに エスケープにピリオド 「 \. 」 でピリオドの文字として認識したうえで、php と文字をいれているので、要するに「 .php 」という拡張子を指定しており、最後のドルマークが行の最後であることから、「 .php 」で最後終わる文字列であることが指定されている。また丸括弧で囲った/path/以降の文字列と拡張子の部分は、後で $1 として参照できる。
例:http://www.mydomain.com/path/login_form/passcheck/key_check.php
上記4番とこの例は合致し、下記の変数に値が入る
ここではよく利用させる規則のみ説明する。注意:~ マークの行は正規表現扱いとなるため、ピリオドなどは振る舞いが下記の形にかわる。
記号 | 役割 |
^ | 行の先頭を意味する。通常 http://server.name.com の部分は含まれないためドキュメント先頭の / から始まる事を意味させることになる。 |
$ | 行の終端を意味する。 |
. | ピリオド。改行を除く任意の1文字(漢字も含む)を意味する。よって拡張子などに使われる文字としてピリオドを使いたい場合は、\. のようにエスケープ記号をピリオドの前にいれ、文字であることを認識させる必要がある |
( ) | 丸括弧。パターン合致結果の変数化。クラスと違い、文字ごとに判定されるのではなく、文字列全体とマッチ判定する。また合致した文字列は、後方で $1 として参照できる。(括弧が複数あれば、$2, $3 と参照できる |
[ ] | 角括弧。キャラクタのクラス化。例、[0-9] これは数字列の場合に合致する。[^0-9] この場合は、数字列以外を指す。 |
| | 縦棒(本当は半角)。論理和を意味する。よく利用されるのは gif|png|jpg のように、拡張子判定をする場合に使われる |
* | アスタリスク。直前のパターンの0回以上の繰り返し。注意するべきは0回以上であるということ。 |
+ | プラス。直前のパターンの1回以上の繰り返し。アスタリスクと違い1文字は存在しないと合致しない。 |
? | クエスチョン。直前のパターンが0回または1回現われる |
upstreamは、リバースプロキシーやロードバランサなどに利用するサーバーセットを記述するディレクティブであり、upstream 名を、location ディレクティブの中の、 proxy_pass に指定することで作動する。基本は、httpブロックの中に以下のように設定する。公式解説
upstream load_balancer { <- upstream 名はなんでもOK。 ip_hash; <- IPをhashして、接続元IPが同じ場合、接続するサーバーを同じにする。 least_conn; <- 一番少ない接続サーバーへの接続優先 server 127.0.0.3:8000 down; server 127.0.0.3:8001 weight=5; <- weight は複数サーバーの時のバランス確率。 server 192.168.0.1:8000 max_fails=3 fail_timeout=30s; server 192.168.0.1:8001 backup; } server { listen 80; server_name big.server.com; access_log logs/access.log; location / { proxy_pass http://load_balancer; } }
serverオプション | 例 | 概要 |
weight= | 5 (初期値=1) | 全サーバーのweight値の合計を分母(但しbackupサーバは除く)にし、ここで分子を指定することで、この比率がサーバー群の中の対応サーバーの分散比率とする |
max_fails= | 3 | 接続失敗時の最大チャレンジ回数 |
fail_timeout= | 30s | 接続失敗を判断するタイムアウト時間。 但し proxy_connect_timeout と proxy_read_timeout によっても関係する。 |
down | 常にダウンしているサーバーに指定。但しip_hash指定があればハッシュは作成される | |
backup | backup指定がない通常サーバーがすべてダウンした時にこのサーバーに接続する |
rewtite文はよく使われると思うが、正規表現の関係で意味不明な文になりやすく、説明もすでに正規表現を理解している前提が多いのでここでは簡単にわかるように説明したい。
例) rewrite ^$ http://$host/chnge/$1;
nginxでは、apacheでいう、mod_php のようなものが存在しません。そのためphpの展開処理は、php-fpm というプロセスを起動し、nginx側からはポートを利用してアクセスする形になります。そのため、php の処理部分だけを、他のサーバーに処理させることも容易です。
# yum install php-fpm # chkconfig php-fpm on
※phpをソースからインストールする場合は、configur 設定で、php-fpm を enable にすると一緒にインストールされる。
修正箇所の例(すでに初期値が設定されているので設定の必要はないが参考までに)
# vi /etc/php-fpm.d/www.conf user = nginx group = nginx pm.max_children = 5 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 2 pm.max_requests = 200
※php-fpmの標準ポートは9000番です。また最初は127.0.0.1 (自分)にだけ、アクセス許可されています。
nginx.conf のサーバー設定の中に、以下のlocationディレクティブを追加する。
location ~ \.php$ { root /usr/local/nginx/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $request_filename; include fastcgi_params; }
※またサーバ設定の index 設定にも、index.php を追加しておくこと。
location ~ \.php$ { root /usr/local/nginx/html; fastcgipass unix:/var/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $request_filename; include fastcgi_params; }
また /etc/php-fm.conf もそれに合わせて修正する。
; listen = 127.0.0.1:9000 listen = /var/run/php-fpm/www.sock
yumで、php-fpmをインストールしている場合は、servceコマンドで起動できる。
# service php-fpm start
その後、nginxも再起動させる。
# service nginx restart
再起動
# nginx -s reload
# nginx -t -c ./nginx.conf
なぜか location ディレクティブ内でしか認識されない。バグ?
設定 | 意味 |
server_tokens off; | nginxのバージョンを表示させない。 |
etag off; | エンティティタグを利用しない。 |
add_header X-Frame-Options SAMEORIGIN; | クリックジャッキング対応として、自身と生成元が同じフレーム内に限りページを表示する設定 |
add_header X-XSS-Protection "1; mode=block"; | クロスサイトスクリプティング(XSS)に対するフィルタ機能を強制的に有効 |
add_header X-Content-Type-Options nosniff; | X-Content-Type-Options レスポンスヘッダーの値に nosniff を設定して送信すると、Internet Explorer が MIME Sniffing 機能で content-type 宣言を回避するのを防止 |
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com; img-src 'self' https://ssl.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; object-src 'none'"; | Content Security Policy (CSP) は、クロスサイトスクリプティング (XSS) やデータインジェクション攻撃を含む、よく知られた種類の攻撃を検出して軽減。左記は特定サイトは除外 |
add_header Strict-Transport-Security 'strict-transport-security: max-age=31536000; includeSubDomains'; | SSL利用を推奨 |
※autoindex off;は初期値だが、むやみに on にしない。
nginxの通信 body サイズの初期値が1MB であるため、ファイル転送などで これを超えるファイルサイズを転送しようとすると発生する。
# vi nginx.conf server { client_max_body_size 20M; }
上記のようにサーバーディレクティブにbodyサイズの上限を変更する。