Linux

nginxを動かしてみる

2020-07-17

Apache HTTP Serverはもう古い!

ということで、彗星の如く現れた、近い将来Apacheサーバーを追い越すであろうWebサーバー「nginx」(エンジンエックス)をさわっておきましょう。

ちなみに記事の内容は、ConoHa VPSにSSHで接続するでDebianサーバーを立てた状態を前提にしています。

カピバラ

設定の煩雑さもかなり改善されていて、これから先Apache2ではなくnginxを使わない理由が見当たらないのです

注意

この記事の内容は、nginxを理解することを最優先にするために、全てroot権限で実行しています。
内容をトレースしながら本番環境を作るのは避けてください。

nginxについて理解ができたら、自分の力でもう一度サーバーを作り直しましょう。

ユーザーのアクセス権を厳格に設定し、nginxの設定ファイルもセキュリティを厳しい内容に書き換えたうえで、です。

一度勉強をして理解し、その上で本番に臨む。
ウェブ開発はそれくらい慎重でないといけません。

nginxのインストール

公式ドキュメントを見よう

nginxは、ググって出てきた情報を元にインストールをしてみたもののうまく動かない可能性が高いです。

Linuxディストリビューションごとに別パッケージで管理されており、別の手順が必要になるからです。

nginxの公式ドキュメントではディストリビューションごとにインストールの手順を公開しているので、そちら見るのがオススメです。
(英語ですがコマンドだけ見れば大体理解できるはず。)

公式インストールガイドはこちら

ちょっと公式見てもわからんわって人は、ConoHa VPSにSSHで接続するで紹介している内容通りにVPSを構築した環境であれば、この後説明する内容をそのままトレースしてもうまくいくはずです。

インストールしていく

公式ではsudoコマンドを使っての説明になっていますが、今回はnginxの理解と説明が目的なためrootユーザーで済ませました。
(非公式な環境でnginxについて勉強し、それが済んだら本番環境はまた別に作成する、くらいの心持ちで勉強するべし)

まずは依存パッケージをインストール
> apt install curl gnupg2 ca-certificates lsb-release

aptにnginxのdebian用パッケージのurlを登録
> echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" \
    | tee /etc/apt/sources.list.d/nginx.list

apt-keyにnginx_signing.keyを書き込み
> url -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -

apt-keyに追加した内容を確認
> apt-key fingerprint ABF5BD827BD9BF62

結果が次のようになっていればOK
573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62

追加したdebian用パッケージのurlからnginxファイルを取得
> apt update

nginxをインストール
> apt install nginxt

それぞれコマンドがエラーなく実行できればインストール完了です。

起動しているか確認してみる

インストールすると自動的にnginxのプロセスが立ち上がっているかもしれませんが、念のため起動コマンドを実行しておきましょう。

> nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()

(すでに起動していても、上記のようなメッセージが出るだけですので。)

http://xxx.xxx.xxx.xxx/(xxxは自分のVPSサーバーのIPアドレス)にブラウザから接続してみると、

あっけなく表示されました。

カピバラ

こういうのは初めはもっとエラーが出たり設定しないと動かなかったりするものだとばかり。

起動・停止・再設定

  • nginx …起動(引数をつけない)
  • nginx -s stop …強制終了
  • nginx -s quit …終了
  • nginx -s reopen …設定再読み込み

nginx -hで確認することができます。

# nginx -h
nginx version: nginx/1.18.0
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

デフォルトのページを差し替えてみる

せっかくHTTPサーバーを入れたら、何か自分のオリジナルのページを表示させてみたいですよね?
ということで、まずはデフォルトで表示されたページを自分オリジナルのページに書き換えてみましょう。

先ほどブラウザからアクセスして表示された「Welcome to nginx!」のページは /usr/share/nginx/html/index.htmlファイルです。
(インストールのしかたによって変わる可能性高いです。ファイルが見つからなかったらこの章を飛ばしても問題なしです。)
このファイルを書き換えて、内容が反映されるか確認してみましょう。

> nano /usr/share/nginx/html/index.html

内容を次のように書き換え

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ようこそエンジンエックスへ!</title>
</head>
<body>
<h1>ようこそエンジンエックスへ!</h1>
<p>エンジンエックス、サイコーのWebサーバーです!ヒャハー!</p>
</body>
</html>

そしてhttp://xxx.xxx.xxx.xxx/(xxxは自分のVPSサーバーのIPアドレス)にブラウザから接続してみると

オリジナルの内容が表示されました。

静的なファイルを提供するだけなら、既に十分運用できる状態ですね。

設定ファイルを読んでいこう

Apache HTTP Serverの設定ファイルはXML形式でしたが、nginxはもっとシンプルな形式で簡潔になっています。

nginxの設定ファイルは、/etc/nginx/nginx.confです。

開いて中を見てみると

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/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;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

こんな感じになっています。

ぱっと見、ごちゃごちゃして見えるかもしれませんが、この設定ファイルの文法はシンプルな2つのルールで成り立っています。

単純命令(simple directive)

文法その1はsimple directive(直訳すると「単純命令」)は、命令と値だけで構成されます。

命令 値;

先ほどの設定ファイル(nginx.conf)の最初の2行なんかがそうですね。

user  nginx;
worker_processes  1;

コンテキスト(context)

文法その2はcontext(コンテキスト)です。

IT用語的に直訳すると制御情報というのが妥当ですが、イメージしづらいのでコンテキストとそのまま呼ぶことにしてしまいましょう。

コンテキストはコンテキスト名と波カッコ{bracket}で構成されます。

context-name {

}

nginx.confの8行目と10行目がコンテキストの記述です。

events {
    worker_connections  1024;
}

events {} の中にあるのはworker_connectionsという単純命令で、ワーカーコネクションは1024に設定する、という内容になっています。

このようにコンテキストは単純命令とコンテキストを複数内包することができます。

シャープ(#)から行末はコメント扱い

シャープ(#)から行末まではコメントとみなされます。

# このようにシャープの後はコメントです
ここはコメントではありません
カピバラ

コメントも文法ルールとしてカウントすると3つあるということになる

nginx.confにコメントをつけてみた

と、いうことで、nginx.confの内容を、1行ずつ全てコメントをつけてみました。

# ワーカープロセスはnginxユーザーで実行される
user  nginx;

# ワーカープロセスは1つのみ
worker_processes  1;

# エラーログは/var/log/nginx/error.logに記録される
# ログレベルはwarn
error_log  /var/log/nginx/error.log warn;

# プロセスIDは/var/run/nginx.pidに書き込む
pid        /var/run/nginx.pid;


# イベント(≒アクセス)に対する設定のコンテキスト
# パフォーマンスチューニングの時しか触らなくてOK
events {
    worker_connections  1024;
}


# HTTPサーバー命令コンテキスト
http {

    # /etc/nginx/mime.typesファイルを設定ファイルとして読み込む
    include       /etc/nginx/mime.types;

    # レスポンスタイプは特に指定されない設定
    # (application/octed-streamは指定しない的な意味になる)
    default_type  application/octet-stream;

    # ログの書式を設定 設定名はmainとする
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # アクセスログは/var/log/nginx/access.logに書き込む
    # 書式はmainで設定されたものを適用
    access_log  /var/log/nginx/access.log  main;

    # システムコールsendfile()を利用する(offが安定)
    sendfile        on;
    #tcp_nopush     on;

    # HTTP KeepAliveがタイムアウトする時間は65秒
    keepalive_timeout  65;

    # 通信をgzip圧縮する
    # (デフォルトではコメントアウトしてあるのでoff)
    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

nginx.conf内で登場する命令の公式説明をリンクしておきました。

conf.d/defaults.confの内容にコメントをつけてみた

続いて、nginx.confの最後に読み込んでいる/etc/nginx/conf.d/*.confの内容も見てみましょうかね。
conf.dの中には、default.confの1ファイルしかありません。

カピバラ

ファイルが沢山あったらページ閉じようかと思ってた人、いると思います。
安心して下さい。ホントにコレで終わりです。

default.confの内容にコメントを加えたものを紹介します。
さらっと読めば、イメージが伝わるかなと思います。

英語のコメントが最初から書いてあったもの、日本語のコメントがケンヂまるが付け足したコメントです。

# サーバー設定
# (複数のserver {}を運用することができる)
server {

    # ポート80をリッスン
    listen       80;

    # httpリクエストヘッダのHostフィールドが
    # localhostの時はサーバーで処理する
    server_name  localhost;


    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    # ルートへのアクセスは/usr/share/nginx/htmlディレクトリ内の
    # ファイルで対応する
    # http://example.com/のようにファイルを指定しないで
    # アクセスされた場合はindex.htmlかindex.htmを表示する。
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    # 404エラー用ページを設定
    # デフォルトでは404.htmlは用意されていない。
    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    # 500エラー、502エラー、503エラー、504エラーは、
    # /usr/share/nginx/html/50x.htmlを表示する
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    # コメントアウトを解除すると.phpファイルへのアクセスは
    # ローカルで動いているAapcheサーバーに渡す
    # (CGIはApacheサーバーに処理させる場合の設定)
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    # コメントアウトを解除すると、.phpファイルねのアクセスは
    # ローカルのポート9000で待機しているFastCGIサーバーに渡す
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #location ~ /\.ht {
    #    deny  all;
    #}
}

default.confで内で登場する命令の公式説明をリンクしておきました。

ほとんどがlocationコンテキストでの設定になっていますが、locationで指定したuriをマッチした部分はこう処理しますよという宣言をもれなく書いていくことで、phpファイルはこう処理する、pythonファイルはこう処理する、cssファイルはこう処理する、といったような制御ができるようになるわけです。

今さらですが注目していただきたいのが、20〜23行目です。

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

デフォルトのページを差し替えてみるで/usr/share/nginx/html/index.htmlを書き換えるとブラウザから表示されるページが変わりましたが、その理由はここでインデックスページが設定されていたからだったのでした。

CGIとか動かせるの?nginx単体ではCGIを動かすことはできません。が、しかし。

default.confを見てもらえるとわかるように、phpファイルなどのCGIとして実行させたいファイルに対してのアクセスは、Apacheや他のCGIサーバーにリダイレクトする設定しか示されていません。

つまり、nginx単体ではCGIを動かすことはできません。しかし、他のCGIサービスに処理を丸投げすることで、安全性を提供しつつ動的ページも提供できる、という設計になっています。

ここ、Apacheサーバーと大きく異なる部分です。

あとがき

僕はPythomプログラマなのですが、作ったプログラムを公開する手段としてnginx+uWSGI+Djangoの環境を構築中です。
Apacheサーバーとnginxのどちらを選択しようか迷っていたのですが、実際に使ってみてnginx一択だなと思ったので、「お、Apacheより簡単じゃん」と思っておらえたらと思って今回の記事を書いた次第です。

-Linux

© 2022 ヂまるBlog