2018年9月15日土曜日

FreeBSD で nginx に挑戦してみた(その2:nginx の設定と初起動)

 前回,FreeBSD で nginx に挑戦してみた(その1)として,FreeBSD に nginx をインストールする話を書いた。 今回は,設定について書いていこう。

nginx の設定ファイルの場所と起動方法


 nginx の設定ファイルは,FreeBSD の場合は,
/usr/local/etc/nginx/
の下に置かれる。 ここにほぼすべての設定を書くイメージになるが,メインとなる設定は
/usr/local/etc/nginx/nginx.conf
である。

 その設定ファイルの前に,FreeBSD での起動方法について書いておこう。
FreeBSD では,まず /etc/rc.conf に以下を書かないといけない。
nginx_enable="YES"
これがないと,下記の起動コマンドを入れても起動してくれない。
 逆に,これを書いておくと,FreeBSD の起動時に nginx を自動で起動してくれる。

 起動や停止は,以下のように打てばよい。
 起動:service nginx start
 停止:service nginx stop
再起動:service nginx restart
再読込:service nginx reload


nginx 設定ファイルの構成要素:ディレクティブとコンテキスト


 さて,いよいよ nginx の設定ファイルの内容について書こう。これが結構量が多い。 ここでの話は Beginner’s Guide の中の「Configuration File’s Structure」に書いてある。

 まず,設定ファイル(/usr/local/etc/nginx/nginx.conf)の構成要素について書こう。
設定ファイルには,いろんな設定項目と指定する値を書き並べる。 この設定項目を表す単語をディレクティブ(命令)と呼ぶ。 各ディレクティブは,値のみを持つ場合とブロック({と}で囲まれている)を持つ場合がある。 値のみを持つ場合を「シンプルディレクティブ」と呼ぶ。 シンプルディレクティブはセミコロン(;)で終端する。
(シンプルディレクティブの例)
    include            mime.types;

ブロックを取る場合を「ブロックディレクティブ」と呼ぶ。 しかし,ブロックディレクティブは多くの場合(私がみた限りは全部そうなのだが…),中にさらにディレクティブを書き並べて,階層構造を作っている。 このような階層構造になっているブロックディレクティブのことを「コンテキスト」と呼ぶらしい。
(コンテキストの例)
    location / {
        root /data/www;
    }


nginx 設定ファイルの構造


 設定ファイル (nginx.conf) は,それ自体がコンテキストであり,「main コンテキスト」と呼ばれる。 main コンテキストは以下のような構造を取る。
(main コンテキストの構造)
シンプルディレクティブ
シンプルディレクティブ
・・・

events{
 (events の設定:接続処理関連)
}

http{
 (http の設定:web サーバーの設定)
}

mail{
 (mail の設定:mail サーバーの設定)
}

stream{
 (stream の設定:TCP/UDP 関連の設定)
}
 ここの先頭に並ぶシンプルディレクティブは,nginx 全体の設定(主にcore モジュールの設定かな?)を行っている。 また,events コンテキストは,接続処理関連のディレクティブを入れる場所みたいである。 http コンテキストは,サーバーの設定を書くコンテキストであり,ほとんどの設定はこの中に書かれると言ってもいいぐらいである。 mail コンテキストと stream コンテキストについては,まだ全然わかっていないので,今回は書かないつもりである。 それぞれの項目については,それぞれ以下のページに詳しいことが書いてある。
 ・シンプルディレクティブ:Core functionality
 ・events コンテキスト:Core functionalityevents 項目
 ・http コンテキスト:Module ngx_http_core_modulehttp 項目
 ・mail コンテキスト:Module ngx_mail_core_modulemail 項目
 ・stream コンテキスト:Module ngx_stream_core_modulestream 項目

特定のディレクティブの内容を知りたい時は,以下のリストからたどると簡単に説明にたどり着くことができる(英語だけど…)。
 Alphabetical index of directives:ディレクティブをアルファベット順に並べたリスト(サードパーティ製を除く)

ちなみにこんなリストもある。
 Alphabetical index of variables:変数をアルファベット順に並べたリスト(サードパーティ製を除く)

次に http コンテキストの概略を示そう。


http コンテキストの構造


 http コンテキストは,web サーバーとしての設定を行う。 構造としては,下記のような構造をとる。
http {
(サーバー共通の設定)

 server {
  (仮想サーバー1に共通の設定)
  location {
   (locationの設定)
  }
  location {
   (location 2の設定)
  }
  ・・・・・(必要ならもっと続く…)
 } # server

 server {
  (仮想サーバー2に共通の設定)
  location {
   (locationの設定)
  }
  location {
   (location 2の設定)
  }
  ・・・・・(必要ならもっと続く…)
 } # server

 ・・・・・(必要ならもっと続く…)
} # http

 http コンテキストは,web サーバーの設定を記述する場所であり,先頭にサーバー全体に共通する設定を記載する。 その後に server コンテキストとして,複数設定可能なサーバー(仮想サーバーを含む)の設定を記載する。 本来の web サーバーも仮想 web サーバーも特に区別はなく,ある意味すべてが仮想サーバーと考えるみたい。 後で記載する server_name ディレクティブに記載したサーバー名がそのサーバーの名前なので, server_name ディレクティブに本来持つ URL を記載すればそれが通常のサーバーとなる(みたい)。 (仮想)サーバーが複数ある時には,この server コンテキストが複数並ぶことになる。 server コンテキストは,ポート番号ごと,仮想サーバーごとに必要となる。

 server コンテキストの中では,各仮想サーバーの設定を記載する 先頭には仮想サーバー全体の設定を記載し,その他に複数の location コンテキストが並ぶ。 この location コンテキストは,仮想サーバー内の特定のディレクトリや特定のファイル,あるいは特定の拡張子を持つファイルに対する処理を記載する。 location コンテキストの記載は,いろんなことをさせようとすると,とても多くなったりする。

 ・server コンテキスト:Module ngx_http_core_moduleserver 項目
 ・location コンテキスト:Module ngx_http_core_modulelocation 項目

 location コンテキストについては次回以降に記載しよう。


nginx 設定ファイル:シンプルな例


 これまでは,一般的な設定ファイルの定義や構造の話だったが,一度具体例を示しておこう。 以下が比較的シンプルな nginx の設定ファイルである。
(nginx 設定ファイルのシンプルな例)
user www www;
worker_processes  2;  # cpu has 4 cores
error_log  /var/log/nginx/error.log error;
pid        /var/run/nginx.pid;
# ==================================================================
events {
    worker_connections  500;
    use                 kqueue;
}
# ==================================================================
http {
    server_tokens      off;
    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         /var/log/nginx/access.log  main;
    charset            UTF-8;
    sendfile           on;
    tcp_nopush         on;
    keepalive_timeout  75;
    gzip               on;
    # ---------------------------------------------------------
    server {
        listen       80 default_server;
        server_name  www.xxxxx.com yyy.xxxxx.com zzz.xxxxx.com;
        location / {
            root   /usr/local/www/data;
            index  index.html /index.html;
        }
    }
}
 かなり多くの項目があるが,困ったことにこれでもシンプルな方である…。
ちなみに,公式サイトには「完全な」サンプルが載っている。
https://www.nginx.com/resources/wiki/start/topics/examples/full/

 今回の例を上から少し説明しておこう。 項目の先頭にある各ディレクティブ名は,公式サイトの記載ページ(英語)へのリンクをつけている。

user ディレクティブは web サーバープロセスのオーナーアカウントとグループである。ここではアカウント名もグループ名も「www」としている。グループ名は省略することが可能である。記載できるのは main コンテキストのみである。

worker_processes ディレクティブは,nginx で起動するプロセス数であり,CPU のコア数やハードディスクの数などで決まるが,よく使われるのが CPU のコア数と同じにする作戦である。コアが4個なら4とするらしい。数字が少々大きくても特に問題はないみたい。 「auto」という選択肢もある。記載できるのは main コンテキストのみである。

error_log ディレクティブは,エラーログを記載するファイル名を指定する。2個めのパラメーターはログレベルを表し,debug, info, notice, warn, error, crit, alert, emerg の値を取りうる。 この中では debug が一番情報が多いが,その分多くのファイルサイズを必要とする。 「error」レベルなら,エラーがあった場合にログに記載される。「info」なら,なにかあるごとに記載される感じがする。 このパラメーターは省略可能であり,省略するとデフォルトの「error」レベルとなる。 mainhttpmailstreamserverlocation のコンテキストに記載できる(どこにでも書ける感じ)。

pid ディレクティブは「pid」(process ID) を記載するファイル名を指定する。記載できるのは main コンテキストのみである。

worker_connections ディレクティブは,一つの worker_process に一度に接続できる接続数の最大値である。この数が接続の上限を決めることになる。記載できるのは events コンテキストのみである。

use ディレクティブは,接続方法を指定する。通常は一番効率のいい接続方法を自動で選ぶので,記載の必然性はないみたい。FreeBSD なら「kqueue」,Linux なら「epoll」がいいらしい。記載できるのは events コンテキストのみである。

server_tokens ディレクティブは,web サーバーとしてクライアントに送り返す server response header フィールドに「nginx」の文字列や,ビルド番号を記載するかどうかを指定する。「on」なら nginx を記載,「off」なら記載しない。「build」ならビルド番号も記載するみたい。コマーシャル版なら「string」として特定の文字列を記載することも可能みたい。 httpserverlocation のコンテキストに記載できる。

include ディレクティブは,他のファイルを読み込みたい時に記載する。ここでは「mime type」を記載したファイルを読み込むことを指示している。ワイルドカードで指定することもできるらしい。どのコンテキストにも記載可能である。
(include の例)
    include mime.types;
    include vhosts/*.conf;

default_type ディレクティブは,デフォルトの MIME タイプを記載する。types ディレクティブに記載した中から選べるが,普通は mime.types ファイルを読み込み,その中にある MIME タイプを選択する。httpserverlocation のコンテキストに記載できる。

log_format ディレクティブは,ログに記載する項目を指定する。 ここでは,「main」という名称でログの記載項目を定義している。 指定をしなくても「combined」という名称で定義されたものが予め定義されているらしい。
log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
記載できるのは http コンテキストのみである。

access_log ディレクティブは,アクセスログのファイル名と,log_format ディレクティブで定義したログフォーマットの定義名を記載する。 httpserverlocation のコンテキストと,location コンテキスト中の if ディレクティブに記載できる。

charset ディレクティブは,web サーバーとしてのレスポンスの Content-Type”response header フィールドに出力する character set を指定する。httpserverlocation のコンテキストと,location コンテキスト中の if ディレクティブに記載できる。

sendfile ディレクティブは,「sendfile()」API を使用するかどうか,を指示する。 sendfile()を使うとカーネル空間内でファイルの読込みと送信が完了するため、効率良くファイルをクライアントに送信できるらしい…。よくわからん…。FreeBSD では使うといいみたい。Linux でも意味はあるかもしれないが,記載がないのでよくわからない…。デフォルトでは off である。 httpserverlocation のコンテキストと,location コンテキスト中の if ディレクティブに記載できる。

tcp_nopush ディレクティブは,FreeBSD なら TCP_NOPUSH ソケットを使うかどうかを指定する。Linux なら TCP_CORK ソケットを使うかどうかの指定になる。これは sendfile ディレクティブが on になっている時のみ有効となる。httpserverlocation のコンテキストに記載できる。

keepalive_timeout ディレクティブは,クライアント keep-alive 接続のサーバー側でのアクティブ時間を指定する。ゼロなら keep-alive 接続は無効になる。httpserverlocation のコンテキストに記載できる。

gzip ディレクティブは,サーバーとしての応答の際に gzip で圧縮するかどうかを指定する。 httpserverlocation のコンテキストと,location コンテキスト中の if ディレクティブに記載できる。

listen ディレクティブは,サーバーとして受け取る IP アドレスやポート番号を指定する。
(listen の例)
listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000;
listen unix:/var/run/nginx.sock;
最後の例は UNIX-domain sockets を受け取る指定である(実はあまりわかってない…)。
2番目以降のオプションに「ssl」をつけると,https 接続を指定することになる。 「http2」オプションをつけると,HTTP/2 接続を受け付ける。 「default_server」を指定すると,なにかあった際にはその仮想サーバー名で接続しようとする。省略すると最初に定義された仮想サーバーがデフォルトサーバーとなる。default_server は同じポート番号に対して1個のみ指定できる。
このディレクティブはオプションも多いので,listen を読んでみてほしい。 記載できるのは server コンテキストのみである。

server_name ディレクティブは,仮想サーバーとしてサーバー名を指定する。これがなければサーバーマシンが本来持っているサーバー名を持つサイトを意味する。 記載できるのは server コンテキストのみである。

root ディレクティブは,そのコンテキストに対するルート PATH を指定する。 例えば,
    location /i/ {
        root /data/w3;
    }
とあれば,“/i/top.gif”というリクエストに対して,「/data/w3/i/top.gif」を返す。 パスは「$document_root」や「$realpath_root」などの変数で指定も可能である。 httpserverlocation のコンテキストと,location コンテキスト中の if ディレクティブに記載できる。

index ディレクティブは,リクエストが「/」で終わっている時に,index として与えるファイル名を指定する。今回の例なら,まずは index.html を探し,なければルートディレクトリの index.html を指定することになる。 httpserverlocation のコンテキストに記載できる。


nginx を起動してみよう


 他の設定ファイルは,とりあえずいじらなくてもいい。 となれば,「service nginx start」として起動してみよう。
(起動の成功例)
# service nginx start
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.
このようになれば,うまく起動できている。
# cat /var/run/nginx.pid
として,process ID を表示できるはずである。

 アクセスしてみると,以下のようなものが表示されるはずである(最後の test9 という文字列は私が加えたもの)。


 再起動させると以下のようになる。設定ファルのチェックをしてからプロセスを止め,もう一度設定ファルをチェックしてから起動し直している。 2回目の設定ファルのチェックは本来必要ないが,起動時(再起動じゃない時)の手順をそのまま使っているから起動直前のチェックが入っていると思う。
(再起動の例)
# service nginx restart
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Stopping nginx.
Waiting for PIDS: 75655.
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.

 うまく行かなかった時は,下記のような感じになる。 ここでは,わざと設定ファイルの「user」ディレクティブを「XXXuser」とすることでエラーを吐かせている。
(起動の失敗例)
# service nginx start
Performing sanity check on nginx configuration:
nginx: [emerg] unknown directive "XXXuser" in /usr/local/etc/nginx/nginx.conf:3
nginx: configuration file /usr/local/etc/nginx/nginx.conf test failed
Starting nginx.
nginx: [emerg] unknown directive "XXXuser" in /usr/local/etc/nginx/nginx.conf:3
/usr/local/etc/rc.d/nginx: WARNING: failed to start nginx
[1]    75632 exit 1     service nginx start


次回は location コンテキストと nginx で cgi を使う場合について記載しよう。

FreeBSD で nginx に挑戦してみた(その3)に続く

0 件のコメント: