nginx

提供: ArchWiki
2023年5月29日 (月) 03:02時点におけるKgx (トーク | 投稿記録)による版 (→‎TLS: 翻訳)
ナビゲーションに移動 検索に移動

nginx ("エンジンエックス"と発音します)は 2005 年から Igor Sysoev(ロシア)によって開発されている、フリーでオープンソースかつハイパフォーマンスな HTTP サーバーかつリバースプロクシで、IMAP/POP3 プロクシサーバーとしても機能します。Nginx は主に、その安定性・多機能・単純な設定・低リソース消費によって知られています。

この記事では nginx の設定方法と、#FastCGI を使って PHP と統合する方法を説明します。

インストール

公式リポジトリから nginx-mainline (メインラインブランチ: 最新の機能・アップデート・修正) か nginx (安定ブランチ: 重要な修正のみを適応) のどちらかをインストールできます。

ノート:

基本的には最新版の利用が推奨されていますが、

  • サードパーティ製のモジュールとの互換性
  • 新規に追加された機能の未知のバグ

などによる影響が懸念される場合は、安定版を使用することを検討してください。

Ruby on Rails のためにインストールするには、Ruby on Rails#Rails パーフェクトセットアップを参照してください。

セキュリティを向上させるために chroot によるインストールをするには、#chroot でインストール を参照してください。

サービスの開始

nginx.service起動/有効化します。

http://127.0.0.1 で提供されるデフォルトのページは、/usr/share/nginx/html/index.html です。

設定

nginx における最初の手順は 公式のビギナーズガイド で説明されています。/etc/nginx/ にあるファイルを編集することで Nginx の設定ができます。メインの設定ファイルは /etc/nginx/nginx.conf です。

より詳しい解説は、公式の ドキュメント にある Nginx Configuration Examples にあります。

以下の例は、最も一般的な使用例をカバーしています。ここでは、ドキュメントのデフォルトの場所 (/usr/share/nginx/html) を使用することを想定しています。そうでない場合は、代わりにあなたのパスを指定してください。

ヒント: DigitalOcean から Nginx configuration tool が提供されています。

設定例

/etc/nginx/nginx.conf
user http;
worker_processes auto;
worker_cpu_affinity auto;

events {
    multi_accept on;
    worker_connections 1024;
}

http {
    charset utf-8;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;
    log_not_found off;
    types_hash_max_size 4096;
    client_max_body_size 16M;

    # MIME
    include mime.types;
    default_type application/octet-stream;

    # logging
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    # load configs
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

一般設定

プロセス数とコネクション数

worker_processes の適当な値を探って下さい。この設定は最終的に nginx が受け入れる接続の数と利用できるプロセスの数を定義します。通常、システムのハードウェアのスレッド数にすると良いでしょう。また、バージョン 1.3.8 と 1.2.5 から worker_processes には auto と設定することができ、最適な値を自動的に検出します (ソース)。

nginx が受け入れる最大接続数は max_clients = worker_processes * worker_connections で計算できます。

別のユーザーで実行する

デフォルトでは、nginx はマスタープロセスを root で、ワーカープロセスを http ユーザで実行します。ワーカープロセスを別のユーザで実行するには、nginx.confuser ディレクティブを変更します。

/etc/nginx/nginx.conf
user user [group];

group が省略された場合は、user と同じ名前のグループが使用されます。

ヒント: systemd を使って root で何もせずに nginx を動かすことも可能です。#systemd を使って非特権で動作させるを参照してください。

サーバーブロック

server ブロックを使うことで複数のドメインを利用することができます。"バーチャルホスト"とも呼ばれますが、これは Apache の用語です。server ブロックの利用方法は Apache とは異なっています。upstream examples も参照してください。

以下の例では2つのドメインの接続をサーバーが待機します: domainname1.domdomainname2.dom:

/etc/nginx/nginx.conf
...
server {
        listen 80;
        server_name domainname1.dom;
        root /usr/share/nginx/domainname1.dom/html;
        location / {
           index index.php index.html index.htm;
        }
}

server {
        listen 80;
        server_name domainname2.dom;
        root /usr/share/nginx/domainname2.dom/html;
        ...
}
...
}

nginx.service再起動して変更を適用します。

クライアントからの接続時にこれらのドメイン名を解決するには、BINDdnsmasq などのDNSサーバーを設定する必要があります。

ローカルマシンでバーチャルホストをテストするには、/etc/hosts ファイルにバーチャルネームを追加してください:

127.0.0.1 domainname1.dom 
127.0.0.1 domainname2.dom
サーバーエントリの管理

異なる server ブロックを異なるファイルに配置することができます。これにより、特定のサイトを簡単に有効または無効にできます。

次のディレクトリを作成します。

# mkdir /etc/nginx/sites-available
# mkdir /etc/nginx/sites-enabled

sites-available ディレクトリに、一つ以上のサーバーブロックを含むファイルを作成します。

/etc/nginx/sites-available/example.conf
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ...
}

http ブロックの最後に、include sites-enabled/*; を追加します。

/etc/nginx/nginx.conf
http {
    ...
    include sites-enabled/*;
}

サイトを有効にするには、シンボリックリンクを作成するだけです。

# ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/example.conf

サイトを無効にするには、アクティブなシンボリックリンクのリンクを解除します。

# unlink /etc/nginx/sites-enabled/example.conf

nginx.serviceリロード/再起動 して、サイト設定の変更を有効にします。

TLS

OpenSSL は TLS をサポートし、Arch のインストール時にデフォルトでインストールされます。

ヒント:
  • SSL を設定する前に ngx_http_ssl_module のドキュメントを読むことを推奨します。
  • Let’s Encrypt は無料の、自動化されたオープンな証明局です。コマンドラインおよび自動設定から直接有効な SSL 証明書を要求するプラグインを利用可能です。
  • Mozilla には、便利な TLS 記事自動化ツール があります。より安全な設定を作成するのに役立ちます。
警告: SSL/TLS の実装を計画している場合は、一部のバリエーションと実装は まだ 攻撃に対して脆弱 であることを知っておいてください。SSL/TLS 内の現在の脆弱性の詳細と、nginx に適切な変更を適用する方法については、http://disablessl3.com/ および https://weakdh.org/sysadmin.html を参照してください。

秘密キーと自己署名証明書を作成します。CSR を必要としないほとんどのインストールにはこれで十分です。

# mkdir /etc/nginx/ssl
# cd /etc/nginx/ssl
# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 1095
# chmod 400 server.key
# chmod 444 server.crt
ノート: -days スイッチはオプションであり、RSA キーサイズは 2048 (デフォルト) まで小さくできます。

CSR を作成する必要がある場合は、上記の代わりに次の手順に従ってください。

# mkdir /etc/nginx/ssl
# cd /etc/nginx/ssl
# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key
# chmod 400 server.key
# openssl req -new -sha256 -key server.key -out server.csr
# openssl x509 -req -days 1095 -in server.csr -signkey server.key -out server.crt
ノート: その他の openssl オプションについては、マニュアル ページ openssl(1ssl) を読むか、豊富なドキュメント を熟読してください。

TLS を使用した /etc/nginx/nginx.conf の開始点は、Mozilla の SSL 設定ジェネレーター です。

nginx.service再起動 して変更内容を反映させます。

Per-user directories

To replicate Apache-style ~user URLs to users' ~/public_html directories, try the following. (Note: if both rules are used, below, the more-specific PHP rule must come first.)

/etc/nginx/nginx.conf
...
server {
    ...
    # PHP in user directories, e.g. http://example.com/~user/test.php
    location ~ ^/~(.+?)(/.+\.php)$ {
        alias          /home/$1/public_html$2;
        fastcgi_pass   unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi.conf;
    }

    # User directories, e.g. http://example.com/~user/
    location ~ ^/~(.+?)(/.*)?$ {
        alias     /home/$1/public_html$2;
        index     index.html index.htm;
        autoindex on;
    }
    ...
}
...

See #PHP implementation for more information on PHP configuration with nginx.

nginx.service再起動 して新しい設定を有効にします。

FastCGI

FastCGI、または FCGI はウェブサーバーでインタラクティブなプログラムを動作させるためのプロトコルです。FastCGI は Common Gateway Interface (CGI) の変種で、ウェブサーバーと CGI プログラムのオーバーヘッドを減らすよう設計されていて、サーバーはより多くのウェブページのリクエストを一度に捌くことができます。

Nginx には FastCGI が組み込まれており多くの外部ツールが動きます、例えば Perl、PHPPython など。これらを使うためにはまず FastCGI サーバーを動かす必要があります。

PHP を動かす

PHP のために FastCGI サーバーを動かす方法は複数あります。ここでは推奨方法として php-fpm を使う方法を記載しています。

手順1: PHP の設定

php をインストールしてください。/etc/php/php.ini の中にある open_basedir に PHP ファイルが含まれているベースディレクトリを (/srv/http//usr/share/webapps/ のような感じで)指定しなくてはなりません:

open_basedir = /usr/share/webapps/:/srv/http/:/home/:/tmp/:/usr/share/pear/

そうしたら必要なモジュールを設定しましょう。例えば sqlite3 を使うなら php-sqlite をインストールして、/etc/php/php.ini の次の行をアンコメントして有効にします:

extension=sqlite3.so
ノート: chroot 環境で nginx を動かしている場合 (chroot は /srv/nginx-jail で、ウェブページは /srv/nginx-jail/www) です。/etc/php/php-fpm.conf ファイルを編集して chroot /srv/nginx-jaillisten = /srv/nginx-jail/run/php-fpm/php-fpm.sock ディレクティブを pool セクション (デフォルトは [www]) の中に記述する必要があります。ソケットファイルのディレクトリが存在しない場合は作成してください。
MariaDB

MariaDB で説明されているようにして MySQL/MariaDB を設定してください。

/etc/php/php.ini の以下の行の 少なくともどれか一つ をアンコメント:

extension=pdo_mysql.so
extension=mysqli.so
警告: PHP 5.5 から、mysql.so廃止 されログファイルにエラーが表示されます。

ウェブスクリプトのために最小権限の MySQL ユーザーを追加することができます。また、/etc/mysql/my.cnf を編集して skip-networking 行をアンコメントすると MySQL サーバーはローカルホストからしかアクセスできなくなります。変更を適用するには MySQL を再起動する必要があります。

ヒント: データベースを利用するために phpMyAdmin, Adminer, mysql-workbench などのツールをインストールしても良いでしょう。
手順2: php-fpm

php-fpm をインストールします:

# pacman -S php-fpm

設定ファイルは /etc/php/php-fpm.conf です。

サービスを動かします:

# systemctl start php-fpm

php-fpm をスタートアップ時に有効にします:

# systemctl enable php-fpm.service
手順3: Nginx の設定

それぞれの server ブロックの中の location ブロックに PHP アプリケーションを次のように記述します:

location ~ \.php$ {
     fastcgi_pass   unix:/run/php-fpm/php-fpm.sock;
     fastcgi_index  index.php;
     include        fastcgi.conf;
}

/etc/nginx/php.conf を作って設定をそこに書く場合、このファイルを server ブロックに入れて下さい。

server = {
    ...
    include  php.conf;
    ...
}

.html や .htm ファイルを PHP として処理したい場合は、以下のようにしてください:

location ~ \.(php|html|htm)$ {
     fastcgi_pass  unix:/run/php-fpm/php-fpm.sock;
     fastcgi_index  index.php;
     include        fastcgi.conf;
}

拡張子が .php でないファイルを php-fpm で動かすことを /etc/php/php-fpm.conf で有効にする必要があります:

security.limit_extensions = .php .html .htm

設定を変えた後は php-fpm デーモンを再起動してください。

# systemctl restart php-fpm
ノート: fastcgi_pass 引数に注意を払って下さい、FastCGI サーバーの設定ファイルで定義された TCP や Unix ソケットでなくてはなりません。デフォルトの php-fpm (Unix) ソケットは
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;

デフォルトの代わりに、通常の TCP ソケットを使うこともできます

fastcgi_pass 127.0.0.1:9000;
ただし Unix ドメインソケットの方が高速です。

Nginx のための FastCGI 設定がある fastcgi.conffastcgi_params が含まれていますが、後者は使われなくなりました。これらのファイルは Nginx をインストールしたときに作られます。

最後に、Nginx が動作している場合は再起動してください:

# systemctl restart nginx

FastCGI をテストしたい場合は、/usr/share/nginx/html/index.php を次の内容で作成して

<?php
  phpinfo();
?> 

ブラウザで http://127.0.0.1/index.php を開いて下さい。

以下は実際の設定例です。例の中では root パスは server の下に直接指定されており (デフォルト設定のように) location の中には置いていません。

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        #fastcgi_pass 127.0.0.1:9000; (depending on your php-fpm socket configuration)
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}

CGI を動かす

この実装は CGI アプリケーションに必要です。

手順1: fcgiwrap

fcgiwrap をインストールしてください。 設定ファイルは /usr/lib/systemd/system/fcgiwrap.socket です。 systemdfcgiwrap.socket を有効化・起動します。

この systemd ユニットファイルは現在 ArchLinux のタスクページで議論されています。思い通りに動くか確認するためにユニットファイルを自分で検査すると良いでしょう。

マルチワーカースレッド

複数のワーカースレッドを生成したい場合は、multiwatchAUR を使用するのが推奨されています。これはクラッシュした子スレッドの再起動の面倒をみてくれます。multiwatch は systemd が作成したソケットを管理できないため、unix ソケットを作成するには spawn-fcgi を使う必要がありますが、ユニットファイルから直接実行した場合は fcgiwrap には問題が生じません。

/usr/lib/systemd/system/fcgiwrap.service から /etc/systemd/system/fcgiwrap.service にユニットファイルをコピーして (存在する場合は fcgiwrap.socket ユニットも)、ExecStart 行を必要に応じて修正してください。以下は multiwatchAUR を使用するユニットファイルです。fcgiwrap.socket が実行中だったり有効になっていないことを確認してください、このユニットと衝突してしまうからです:

/etc/systemd/system/fcgiwrap.service
[Unit]
Description=Simple CGI Server
After=nss-user-lookup.target

[Service]
ExecStartPre=/bin/rm -f /run/fcgiwrap.socket
ExecStart=/usr/bin/spawn-fcgi -u http -g http -s /run/fcgiwrap.sock -n -- /usr/bin/multiwatch -f 10 -- /usr/sbin/fcgiwrap
ExecStartPost=/usr/bin/chmod 660 /run/fcgiwrap.sock
PrivateTmp=true
Restart=on-failure

[Install]
WantedBy=multi-user.target

-f 10 は生成する子スレッドの数に変更してください。

警告: spawn-fcgi-M 660 オプションを使用すると奇妙な動作が発生するため、ExecStartPost 行が必要です。間違ったモードが設定されています。これはバグかもしれません?
nginx の設定

/etc/nginx で、ファイル fastcgi_paramsfcgiwrap_params にコピーします。fcgiwrap_params で、SCRIPT_NAMEDOCUMENT_ROOT を設定する行をコメント化するか削除します。

CGI Web アプリケーションを提供する各 server ブロック内には、次のような location ブロックが表示されます。

location ~ \.cgi$ {
     include       fcgiwrap_params;
     fastcgi_param DOCUMENT_ROOT /srv/www/cgi-bin/;
     fastcgi_param SCRIPT_NAME   myscript.cgi;
     fastcgi_pass  unix:/run/fcgiwrap.sock;
}

fcgiwrap のデフォルトのソケットファイルは /run/fcgiwrap.sock です。

fastcgi_param SCRIPT_FILENAME /srv/www/cgi-bin/myscript.cgi を使用することは、DOCUMENT_ROOTSCRIPT_NAME を設定する代わりのショートカットです。 SCRIPT_FILENAME を使用する場合は、fastcgi_paramsfcgiwrap_params にコピーして、DOCUMENT_ROOTSCRIPT_NAME 行をコメントアウトする必要もありません。

警告: SCRIPT_NAME と DOCUMENT_ROOT が使用されている場合、fcgiwrap は nginx に設定されている他の fastcgi_params を 破棄 します。他のパラメータ (PATH_INFO など) を Nginx 設定を通じて設定できるようにするには、SCRIPT_FILENAME を使用する必要があります。GitHub の問題を参照してください

502 - bad Gateway エラーが繰り返し発生する場合は、CGI アプリケーションが最初に次のコンテンツの MIME タイプをアナウンスするかどうかを確認する必要があります。HTML の場合、これは Content-type: text/html である必要があります。

403 エラーが発生した場合は、CGI 実行可能ファイルが http ユーザーによって読み取りおよび実行可能であること、およびすべての親フォルダーが http ユーザーによって読み取り可能であることを確認してください。

chroot でインストール

chroot に Nginx をインストールすることでセキュリティレイヤーを追加することができます。セキュリティを最大限に高めるために、Nginx サーバーを動かすのに必要なファイルだけを入れて、全てのファイルは出来る限り最小限の権限にします。例えば、なるべく root が所有するようにして、/usr/bin などのディレクトリは読み書きできないようにするなど。

Arch はデフォルトでサーバーを実行するための http ユーザーとグループが設定されています。chroot は /srv/http で動作させます。

この牢獄を作るための perl スクリプトが jail.pl gist にあります。このスクリプトを使用するか、またはこの記事の指示に従って作成するか選ぶことができます。スクリプトは root で実行してください。変更を適用する前に行をアンコメントする必要があります。

必要なデバイスを作成

Nginx には /dev/null, /dev/random, /dev/urandom が必要です。これらを chroot にインストールするために /dev/ フォルダを作成してデバイスを mknod で追加します。chroot が危険になったときでも、攻撃者が /dev/sda1 などの重要なデバイスにアクセスするには chroot から脱出しなくてはならないようにするために、/dev/ を全てマウントはしません。

ヒント: mknod の引数については man mknodls -l /dev/{null,random,urandom} を見て下さい。
# export JAIL=/srv/http
# mkdir $JAIL/dev
# mknod -m 0666 $JAIL/dev/null c 1 3
# mknod -m 0666 $JAIL/dev/random c 1 8
# mknod -m 0444 $JAIL/dev/urandom c 1 9

必要なフォルダを作成

Nginx を適切に実行するためにはたくさんのファイルが必要になります。それらをコピーする前に、ファイルを保存するためのフォルダを作成してください。ここでは Nginx のドキュメントルートが /srv/http/www であると仮定します。

# mkdir -p $JAIL/etc/nginx/logs
# mkdir -p $JAIL/usr/{lib,bin}
# mkdir -p $JAIL/usr/share/nginx
# mkdir -p $JAIL/var/{log,lib}/nginx
# mkdir -p $JAIL/www/cgi-bin
# mkdir -p $JAIL/{run,tmp}
# cd $JAIL; ln -s usr/lib lib 
ノート: 64ビットのカーネルを使っている場合 usr/liblib64usr/lib64 のシンボリックリンクを作成する必要があります: cd $JAIL; ln -s usr/lib lib64cd $JAIL/usr; ln -s lib lib64

そして $JAIL/tmp$JAIL/run を tmpfs でマウントします。攻撃者が RAM を全て喰いつくせないようにサイズを制限すると良いでしょう。

# mount -t tmpfs none $JAIL/run -o 'noexec,size=1M'
# mount -t tmpfs none $JAIL/tmp -o 'noexec,size=100M'

再起動してもマウントが維持されるように、以下のエントリを /etc/fstab に追加します:

/etc/fstab
 tmpfs   /srv/http/run   tmpfs   rw,noexec,relatime,size=1024k   0       0
 tmpfs   /srv/http/tmp   tmpfs   rw,noexec,relatime,size=102400k 0       0

chroot に移住

まず平易なファイルをコピーします。

# cp -r /usr/share/nginx/* $JAIL/usr/share/nginx
# cp -r /usr/share/nginx/html/* $JAIL/www
# cp /usr/bin/nginx $JAIL/usr/bin/
# cp -r /var/lib/nginx $JAIL/var/lib/nginx

そして必要なライブラリをコピーします。ldd を使ってライブラリを確認して適当な場所にコピーして下さい。ハードリンクよりはコピーが推奨されます。攻撃者が書き込み権限を得たときに本当のシステムファイルが破壊されたり改変される可能性があるためです。

$ ldd /usr/bin/nginx
   linux-vdso.so.1 (0x00007fffc41fe000)
   libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f57ec3e8000)
   libcrypt.so.1 => /usr/lib/libcrypt.so.1 (0x00007f57ec1b1000)
   libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f57ebead000)
   libm.so.6 => /usr/lib/libm.so.6 (0x00007f57ebbaf000)
   libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f57eb94c000)
   libssl.so.1.0.0 => /usr/lib/libssl.so.1.0.0 (0x00007f57eb6e0000)
   libcrypto.so.1.0.0 => /usr/lib/libcrypto.so.1.0.0 (0x00007f57eb2d6000)
   libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f57eb0d2000)
   libz.so.1 => /usr/lib/libz.so.1 (0x00007f57eaebc000)
   libGeoIP.so.1 => /usr/lib/libGeoIP.so.1 (0x00007f57eac8d000)
   libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f57eaa77000)
   libc.so.6 => /usr/lib/libc.so.6 (0x00007f57ea6ca000)
   /lib64/ld-linux-x86-64.so.2 (0x00007f57ec604000)
# cp /lib64/ld-linux-x86-64.so.2 $JAIL/lib

/usr/lib の中にあるファイルについては次のワンライナーが使えます:

# cp $(ldd /usr/bin/nginx | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') $JAIL/usr/lib
ノート: linux-vdso.so をコピーしないでください – 実際のライブラリではなく /usr/lib には存在しません。64ビット環境の場合 ld-linux-x86-64.so/lib64 にあるように表示されます。

必要なライブラリとシステムファイル以外のファイルをコピーします。

# cp /usr/lib/libnss_* $JAIL/usr/lib
# cp -rfvL /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf,nginx} $JAIL/etc

chroot のために制限を付けたユーザー・グループファイルを作成します。これにより chroot にアクセスするのに必要なシステムユーザー・グループが攻撃者に漏洩しなくなります。

$JAIL/etc/group
http:x:33:
nobody:x:99:
$JAIL/etc/passwd
http:x:33:33:http:/:/bin/false
nobody:x:99:99:nobody:/:/bin/false
$JAIL/etc/shadow
http:x:14871::::::
nobody:x:14871::::::
$JAIL/etc/gshadow
http:::
nobody:::
# touch $JAIL/etc/shells
# touch $JAIL/run/nginx.pid

最後にパーミッションをできるだけ制限的に設定してください。できるかぎり所有者を root にして書き込み不可にします。

# chown -R root:root $JAIL/
 
# chown -R http:http $JAIL/www
# chown -R http:http $JAIL/etc/nginx
# chown -R http:http $JAIL/var/{log,lib}/nginx
# chown http:http $JAIL/run/nginx.pid
 
# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs sudo chmod -rw
# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs sudo chmod +x
# find $JAIL/etc -gid 0 -uid 0 -type f -print | xargs sudo chmod -x
# find $JAIL/usr/bin -type f -print | xargs sudo chmod ug+rx
# find $JAIL/ -group http -user http -print | xargs sudo chmod o-rwx
# chmod +rw $JAIL/tmp
# chmod +rw $JAIL/run

サーバーがポート 80 (あるいは 0-1024 のどれかのポート) で待機する場合、chroot した実行ファイルに root 権限がなくてもポートを使えるように権限を与えてください:

# setcap 'cap_net_bind_service=+ep' $JAIL/usr/bin/nginx

nginx.service を変更して chroot を起動

nginx.service ユニットファイルを編集する前に、ユニットファイルを /etc/systemd/system/ にコピーして /usr/lib/systemd/system/ のファイルよりも優先されるようにすると良いでしょう。nginx をアップグレードしたときにカスタムした .service ファイルが変更されなくなります。

# cp /usr/lib/systemd/system/nginx.service /etc/systemd/system/nginx.service

chroot で nginx を起動するために systemd ユニットを変更して、pid ファイルを chroot に保存します。

ノート: pid ファイルを chroot ジェイルに保存する必要があるかどうかはわかりません。
/etc/systemd/system/nginx.service
 [Unit]
 Description=A high performance web server and a reverse proxy server
 After=syslog.target network.target
 
 [Service]
 Type=forking
 PIDFile=/srv/http/run/nginx.pid
 ExecStartPre=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -t -q -g 'pid /run/nginx.pid; daemon on; master_process on;'
 ExecStart=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;'
 ExecReload=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;' -s reload
 ExecStop=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid;' -s quit
 
 [Install]
 WantedBy=multi-user.target
ノート: pacman を使用して nginx をアップグレードしても、chroot された nginx インストールはアップグレードされません。上記の手順の一部を繰り返して、手動で更新を行う必要があります。リンク先のライブラリも忘れずに更新してください。

chroot されていない nginx 環境は取り除いてもかまいません:

# pacman -Rsc nginx

chroot されていない nginx 環境を削除しない場合、実行中の nginx プロセスが chroot されているプロセスかどうか確認したくなるときがあるかもしれません。/proc/PID/root シンボリックリンクを確認することでチェックできます。

# ps -C nginx | awk '{print $1}' | sed 1d | while read -r PID; do ls -l /proc/$PID/root; done

ヒントとテクニック

systemd を使用したユーザーサービスの実行

権限のないユーザーが完全に制御して構成できるサーバーインスタンスを実行したい場合は、nginx-user-serviceAUR の使用を検討してください。

systemd を使って非特権で動作させる

nginx.serviceドロップインファイルを使用して、[Service] の下の User と任意で Group を設定します。

/etc/systemd/system/nginx.service.d/user.conf
[Service]
User=user
Group=group

権限昇格に対してサービスを防御することができます:

/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
NoNewPrivileges=yes
ヒント: 制限オプションについて詳しくは systemd.exec(5) を見てください。

それから user が必要なファイルやポートにアクセスできるようにしてください。以下の項目に従って、nginx を起動します。

ヒント: FastCGI サーバー でも同じ設定が望ましい場合があります。

ポート

Linux はデフォルトでは root 以外が 1024 以下のポートを使うことができないようになっています。1024 よりも上のポートは使うことができます:

/etc/nginx/nginx.conf
server {
        listen 8080;
}
ヒント: nginx にポート 80 あるいは 443 からアクセスできるようにしたい場合、ファイアウォールを設定して 80 あるいは 443 から nginx が listen しているポートに転送してください。
また、nginx プロセスに CAP_NET_BIND_SERVICE ケイパビリティを付与することで 1024 以下のポートにバインドできるようになります:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
CapabilityBoundingSet=
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=
AmbientCapabilities=CAP_NET_BIND_SERVICE

PID ファイル

nginx はデフォルトでは /run/nginx.pid を使います。user が書き込み可能なディレクトリを作成して PID ファイルをそこに配置します。systemd-tmpfiles を使用する例:

/etc/tmpfiles.d/nginx.conf
d /run/nginx 0775 root group - -

設定を実行:

# systemd-tmpfiles --create

元の nginx.service に合わせて PID の値を編集:

/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
PIDFile=/run/nginx/nginx.pid
ExecStart=
ExecStart=/usr/bin/nginx -g 'pid /run/nginx/nginx.pid; error_log stderr;' 
ExecReload=
ExecReload=/usr/bin/nginx -s reload -g 'pid /run/nginx/nginx.pid;'

/var/lib/nginx/*

/var/lib/nginx の一部のディレクトリは root として nginx でブートストラップする必要があります。サーバー全体を起動する必要はありません。nginx は設定テストでブートストラップを実行します。一回実行すればそれで十分です。

ログファイル & ディレクトリのパーミッション

設定テストの実行時に root によって所有される壊れたログが作成されます。/var/log/nginx のログを削除して新しく起動してください。 nginx サービスのユーザーから /var/log/nginx に書き込む権限が必要です。パーミッションを変更するかディレクトリの所有者を変更してください。

systemd の別のスクリプト

純粋な systemd では、chroot + systemd の利点を得ることができます。[1] セット ユーザーグループ と pid に基づいて次のようにします。

/etc/nginx/nginx.conf
user http;
pid /run/nginx.pid;

ファイルの絶対パスは /srv/http/etc/nginx/nginx.conf です。

/etc/systemd/system/nginx.service
[Unit]
Description=nginx (Chroot)
After=syslog.target network.target

[Service]
Type=forking
PIDFile=/srv/http/run/nginx.pid
RootDirectory=/srv/http
ExecStartPre=/usr/bin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/bin/nginx -c /etc/nginx/nginx.conf
ExecReload=/usr/bin/nginx -c /etc/nginx/nginx.conf -s reload
ExecStop=/usr/bin/nginx -c /etc/nginx/nginx.conf -s stop

[Install]
WantedBy=multi-user.target

デフォルトの場所を設定する必要はありません。nginx はデフォルトでロードされます。 -c /etc/nginx/nginx.conf ですが、これは良い考えです。

あるいは、パラメータ RootDirectoryStartOnlyyes に設定して chroot として only ExecStart を実行することもできます。(systemd.service(5) を参照) またはマウントポイントが有効になる前、または systemd パス (systemd.path(5) を参照) が利用可能になる前に起動します。

/etc/systemd/system/nginx.path
[Unit]
Description=nginx (Chroot) path
[Path]
PathExists=/srv/http/site/Public_html
[Install]
WantedBy=default.target

作成された nginx.path有効化 し、WantedBy=default.targetWantedBy=nginx.path に変更します|/etc/systemd/system/nginx.service}}

ユニットファイル内の PIDFile により、systemd がプロセスを監視できるようになります (絶対パスが必要です) 望ましくない場合は、デフォルトのワンショットタイプに変更し、ユニットファイルから参照を削除できます。

Nginx Beautifier

nginxbeautifierAUR は nginx の設定ファイルを整形することができるコマンドラインツールです。

より良いヘッダー管理

Nginx のヘッダー管理システムはあまり直感的とは言えません。ヘッダーは特定のコンテキストでしか定義できず、他のヘッダーは無視されます。headers-more-nginx モジュールをインストールすることでこの挙動を変更できます。

nginx-mod-headers-more パッケージをインストールしてください。モジュールは /usr/lib/nginx/modules ディレクトリにインストールされます。

モジュールをロードするには以下をメインの nginx の設定ファイルに追加してください:

/etc/nginx/nginx.conf
load_module "/usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so";
...

基本認証

基本認証ではパスワードファイルの作成が必要です。パスワードファイルは、apache パッケージで提供される htpasswd プログラムを使用するか、nginx-passwd を提供する nginx_passwdAUR を使用して管理できます。詳細は、次のサイトで確認できます。 github ソース

トラブルシューティング

設定の確認

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Error: The page you are looking for is temporarily unavailable. Please try again later. (502 Bad Gateway)

これは、FastCGI サーバーが起動していないか、使用されているソケットの権限が間違っているためです。

502 エラーを修正するには、out thisanswer を試してください。

Arch Linux では、上記のリンクに記載されている設定ファイルは /etc/php/php-fpm.conf です。

Error: No input file specified

1. /etc/php/php.ini の変数 open_basedirnginx.conf の {{ic|root} 引数に指定した正しいパスを含むことを確認します。(通常は /usr/share/nginx/) です。PHP の FastCGI サーバとして PHP-FPM を使用する場合、 fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";location ブロックに追加し、nginx.conf の php ファイル処理用に指定することができます。

2. もう 1 つは、nginx.conflocation ~ \.php$ セクションの root 引数が間違っていることです。root が同じサーバー内の location / と同じディレクトリを指していることを確認してください。または、root をグローバルとして設定し、location セクションで定義しないこともできます。

3. パーミッションの確認:例えば、ユーザー/グループは http 、ディレクトリは 755 、ファイルは 644 です。html ディレクトリへのパス全体が正しいパーミッションを持っている必要があることを忘れないでください。ディレクトリツリーを一括で変更するには、ファイルのパーミッションと属性#まとめて chmod を参照してください。

4. おそらくスクリプトのフルパスを含んだ SCRIPT_FILENAME がありません。 nginx の設定 (fastcgi_param SCRIPT_FILENAME) が完全でも、このエラーは php が requestd スクリプトをロードできないことを意味しています。これは単純にパーミッションの問題であることが普通で、root で php-cgi を実行するか

# spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/bin/php-cgi

php-cgi を起動するグループとユーザーを作成する必要があります。例えば:

# groupadd www
# useradd -g www www
# chmod +w /srv/www/nginx/html
# chown -R www:www /srv/www/nginx/html
# spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/bin/php-cgi

5. chrooted nginx で php-fpm を実行している場合は、chroot/etc/php-fpm/php-fpm.d/www.conf (または /etc/php-fpm/php-fpm.conf 古いバージョンで動作している場合)

Warning: Could not build optimal types_hash

nginx.service を開始すると、プロセスによって次のメッセージが記録される場合があります。

[warn] 18872#18872: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size

この警告を修正するには、http ブロック内のこれらのキーの値を増やします [2] [3]:

/etc/nginx/nginx.conf
http {
    types_hash_max_size 4096;
    server_names_hash_bucket_size 128;
    ...
}

Cannot assign requested address

nginx.service ユニットステータスからの完全なエラーは次のとおりです。

[emerg] 460#460: bind() to A.B.C.D:443 failed (99: Cannot assign requested address)

nginx ユニット ファイルが systemd を使用して network.target の後に実行するように設定されている場合でも、nginx は、構成されているがどのインターフェイスにもまだ追加されていないアドレスでリッスンしようとする場合があります。 nginx の 開始を手動で実行して、これが当てはまることを確認します (これにより、IP アドレスが適切に設定されていることが示されます)。任意のアドレスをリッスンするように nginx を設定すると、この問題が解決します。ユースケースで特定のアドレスをリッスンする必要がある場合、考えられる解決策の 1 つは、systemd を再構成することです。

設定されたすべてのネットワークデバイスが起動し、IP アドレスが割り当てられた後に nginx を起動するには、nginx.service 内の After=network-online.target を追加し、systemd-networkd-wait-online.service起動/有効化にします。

参照