ユーザの新しい古いに関係なく落とし穴に陥り得ます。以下で、頻繁に見かける問題の概要を説明し、それらの問題をどうやって解決するかを説明します。Freenode上の #nginx IRC チャンネルの中で、これらの問題を頻繁に見かけます。
The most frequent issue we see happens when someone attempts to just copy and paste a configuration snippet from some other guide. 表にある全てのガイドが間違っているわけでは無いですが、それらのうちの恐ろしい数がそうです。Linodeライブラリでさえ情報の品質が乏しく、幾つかのNGINXコミュニティのメンバーは訂正するために無駄に試みています。
これらのドキュメントは全ての種類のNGINXのユーザと直接仕事をするコミュニティのメンバーによって作成およびレビューされました。This specific document exists only because of the volume of common and recurring issues that community members see.
あなたの特定の問題に関係する何かをここでYou don’t see something in here related to your specific issue. Maybe we didn’t point you here because of the exact issue you’re experiencing. Don’t skim this page and assume you were sent here for no reason. ここにリストされている何かの間違いをしたので、あなたはここに送られました。
When it comes to supporting many users on many issues, community members don’t want to support broken configurations. 助けを求める前に設定を修正してください。これを読んで設定を修正してください。ざっと読むだけにしないでください。
NEVER use 777
. It might be one nifty number, but even in testing it’s a sign of having no clue what you’re doing. 全てのパスのパーミッションを見て、何が起きているかを考えてください。
To easily display all the permissions on a path, you can use:
namei -om /path/to/check
BAD:
server {
server_name www.example.com;
location / {
root /var/www/nginx-default/;
# [...]
}
location /foo {
root /var/www/nginx-default/;
# [...]
}
location /bar {
root /some/other/place;
# [...]
}
}
これは動作します。Putting root inside of a location
block will work and it’s perfectly valid. What’s wrong is when you start adding location
blocks. If you add a root to every location block then a location
block that isn’t matched will have no root. Therefore, it is important that a root directive occur prior to your location
blocks, which can then override this directive if they need to. 良い瀬手地を見てみましょう。
GOOD:
server {
server_name www.example.com;
root /var/www/nginx-default/;
location / {
# [...]
}
location /foo {
# [...]
}
location /bar {
root /some/other/place;
# [...]
}
}
BAD:
http {
index index.php index.htm index.html;
server {
server_name www.example.com;
location / {
index index.php index.htm index.html;
# [...]
}
}
server {
server_name example.com;
location / {
index index.php index.htm index.html;
# [...]
}
location /foo {
index index.php;
# [...]
}
}
}
なぜ必要の無い時にあまりに多くの行を繰り返すのか。Simply use the index
directive one time. It only needs to occur in your http{}
block and it will be inherited below.
GOOD:
http {
index index.php index.htm index.html;
server {
server_name www.example.com;
location / {
# [...]
}
}
server {
server_name example.com;
location / {
# [...]
}
location /foo {
# [...]
}
}
}
if
¶There is a little page about using if
statements. それは Ifは邪悪 と呼ばれ、本当にそれを調べるべきです。Let’s take a look at a few uses of if
that are bad.
参照
BAD:
server {
server_name example.com *.example.com;
if ($host ~* ^www\.(.+)) {
set $raw_domain $1;
rewrite ^/(.*)$ $raw_domain/$1 permanent;
}
# [...]
}
}
これには実際のところ3つの問題があります。The first being the if
. 私達が今心配しているのはそれです。なぜこれが悪いのか?Ifは邪悪 を読みましたか?When NGINX receives a request no matter what is the subdomain being requested, be it www.example.com or just the plain example.com this if
directive is always evaluated. Since you’re requesting NGINX to check for the Host header for every request. それは極度に非効率です。それはさけなければなりません。Instead use two server
directives like the example below.
GOOD:
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
server_name example.com;
# [...]
}
Besides making the configuration file easier to read. このやり方はNGINXの処理要求を減らします。We got rid of the spurious if
. We’re also using $scheme
which doesn’t hardcodes the URI scheme you’re using, be it http or https.
Using if
to ensure a file exists is horrible. それは意地悪です。If you have any recent version of NGINX you should look at try_files
which just made life much easier.
BAD:
server {
root /var/www/example.com;
location / {
if (!-f $request_filename) {
break;
}
}
}
GOOD:
server {
root /var/www/example.com;
location / {
try_files $uri $uri/ /index.html;
}
}
What we changed is that we try to see if $uri
exists without requiring if
.
Using try_files
means that you can test a sequence. If $uri
doesn’t exist, try
$uri/
, if that doesn’t exist try a fallback location.
In this case, if the $uri
file exists, serve it. If not, check if that directory
exists. If not, then proceed to serve index.html
which you make sure exists.
It’s loaded–but oh-so-simple! This is another instance where you can completely
eliminate If.
“Front Controller Pattern” designs are popular and are used on the many of the most popular PHP software packages; But a lot of examples are more complex than they need to be. For Drupal, Joomla, etc., just use this:
try_files $uri $uri/ /index.php?q=$uri&$args;
注意 - パラメータ名は使用するパッケージに基づいて異なります。例えば:
Some software don’t even need the query string and can read from REQUEST_URI. For example, WordPress supports this:
try_files $uri $uri/ /index.php;
If you don’t care about checking for the existence of directories, you can skip
it by removing $uri/
.
Of course, your mileage may vary and you may require something more complex based on your needs, but for basic sites, these will work perfectly. 常に簡単なものから始め、そこから構築するべきです。
Many example NGINX configurations for PHP on the web advocate passing every URI ending in .php
to the PHP interpreter. これは、サードパーティによる任意のコードの実行を許可するかも知れないので、ほとんどのPHPセットアップ上で深刻なセキュリティ問題を与えることに注意してください。
問題のセクションは通常このようなものです:
location ~* \.php$ {
fastcgi_pass backend;
# [...]
}
Here, every request ending in .php
will be passed to the FastCGI backend. The
issue with this is that the default PHP configuration tries to guess which file
you want to execute if the full path does not lead to an actual file on the
filesystem.
例えば、もし/forum/avatar/1232.jpg/file.phpへのリクエストが作られ、これが存在しないが /forum/avatar/1232.jpgが存在する場合、PHPインタプリタは代わりに /forum/avatar/1232.jpg を処理しようとするでしょう。もしこれが埋め込みのPHPコードを含む場合、コードはその結果実行されるでしょう。
これを避けるためのオプションは:
cgi.fix_pathinfo=0
in php.ini
. これはPHPインタプリタに渡された文字通りのパスだけを試すようにし、ファイルが存在しなければ処理を停止させます。location ~* (file_a|file_b|file_c)\.php$ {
fastcgi_pass backend;
# [...]
}
location /uploaddir {
location ~ \.php$ {return 403;}
# [...]
}
try_files
directive to filter out the problem condition:location ~* \.php$ {
try_files $uri =404;
fastcgi_pass backend;
# [...]
}
location ~* \.php$ {
location ~ \..*/.*\.php$ {return 404;}
fastcgi_pass backend;
# [...]
}
巷にあるあまりにも多くのガイドが情報を取得するために絶対パスに依存しがちです。これは一般的にPHPブロックに見受けられます。When you install NGINX from a repository, you’ll usually wind up being able to toss include fastcgi_params;
in your config. This is a file located in your NGINX root directory which is usually around /etc/nginx/
.
GOOD:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
BAD:
fastcgi_param SCRIPT_FILENAME /var/www/yoursite.com/$fastcgi_script_name;
Where is $document_root
set?serverブロック内にある筈のrootディレクティブによって設定されます。rootディレクティブがありませんか?最初の落とし穴を見てください。
気を悪くしないでください。正規表現を使って混乱するのは簡単です。In fact, it’s so easy to do that we should make an effort to keep them neat and clean. 完全に簡単に、酷いものを追加しないでください。
BAD:
rewrite ^/(.*)$ http://example.com/$1 permanent;
GOOD:
rewrite ^ http://example.com$request_uri? permanent;
BETTER:
return 301 http://example.com$request_uri;
上を見てください。そしてここに戻ってください。そして上に行き、ここに戻ってください。OK. 最初のrewriteは完全なURIから最初のスラッシュを引いたものをキャプチャします。By using the built-in variable $request_uri
we can effectively avoid doing any capturing or matching at all.
http://
¶Very simply, rewrites are relative unless you tell NGINX that they’re not. Making a rewrite absolute is simple. スキーマを追加します。
BAD:
rewrite ^ example.com permanent;
GOOD:
rewrite ^ http://example.com permanent;
上で私達がしたことはrewriteにhttp://
を追加したことだと分かるでしょう。単純で、簡単で、効果的です。
BAD:
server {
server_name _;
root /var/www/site;
location / {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/tmp/phpcgi.socket;
}
}
Yucky. この例では、全てをPHPに渡しています。なぜ?Apache might do this, but you don’t need to. The try_files directive exists for an amazing reason: It tries files in a specific order. NGINX can first try to serve the static content, and if it can’t, it moves on. このことは、PHPは全く巻き込まれないことを意味します。とても速いです。1MBのイメージをphpを通じて数千回提供している場合に対して、直接それを提供する場合は特にそうです。それをどうやってやるかを見てみましょう。
GOOD:
server {
server_name _;
root /var/www/site;
location / {
try_files $uri $uri/ @proxy;
}
location @proxy {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/tmp/phpcgi.socket;
}
}
Also GOOD:
server {
server_name _;
root /var/www/site;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/tmp/phpcgi.socket;
}
}
Easy, right?See if the requested URI exists and can be served by NGINX. If not, see if it is a directory that can be served. If not, then pass it to your proxy. NGINXがリクエストされたURIを直接提供できない場合のみ、プロキシのオーバーヘッドが巻き込まれます。
Consider how much of your requests are for static content (images, css, javascript, etc.). おそらく大量のオーバーヘッドが節約されます。
ブラウザのキャッシュあなたの設定は完璧かも知れませんが、一ヶ月の間そこに座って頭を記憶の壁に打ち付けているでしょう。間違っているのはあなたのブラウザのキャッシュです。何かをダウンロードした時に、ブラウザはそれを保存します。ブラウザはファイルがどうやって提供されたかも保存します。If you are playing with a types{}
block you’ll encounter this.
処置:
これが動作せず、NGINXをVirtualBox内のvirtulaマシーン上で実行している場合は、問題を起こしているのはsendfile()かも知れません。単純にsendfileディレクティブをコメントアウトするか、それを"off"に設定します。ディレクティブはほとんどnginx.confファイルの中で見つかります:
sendfile off;
If you do not explicitly set underscores_in_headers on;
, NGINX will silently drop HTTP headers with underscores (which are perfectly valid according to the HTTP standard). これはダッシュおよびアンダースコアの両方が処理の間にアンダースコアにマップされるために、ヘッダーがCGIにマッピングされる時の曖昧さを避けるために行われます。
どのようなファイルシステムにもデータをホストするために使われない幾つかのディレクトリがあります。These include /
and root
. それらをドキュメントルートとして使うべきではありません。
Doing this leaves you open to a request outside of your expected area returning private data.
これをしないでください!!!(yes, we have seen this)
server {
root /;
location / {
try_files /web/$uri $uri @php;
}
location @php {
# [...]
}
}
When a request is made for /foo
, the request is passed to php because the file isn’t found. This can appear fine, until a request in made for /etc/passwd
. はい。そのサーバ上の全てのユーザのリストを渡しました。幾つかの場合で、NGINXサーバはrootとしてワーカーを実行するようにセットアップされさえします。Yup, we now have your user list as well as password hashes and how they’ve been hashed. これで私達はあなたの箱を所有します。
ファイルシステム階層標準はデータがどこにあるべきかを定義します。確実にそれを読むべきです。The short version is that you want your web content to exist in either /var/www/
, /srv
, /usr/share/www
.
NGINX packages that exist in Ubuntu, Debian, or other operating systems, as an easy-to-install package will often provide a ‘default’ configuration file as an example of configuration methods, and will often include a document root to hold a basic HTML file.
これらのパッケージングシステムは、デフォルトのドキュメントルート内でファイルが修正されたかあるいは存在するかどうかを調べないため、パッケージがアップグレードされた時にコードの紛失に繋がります。熟練したシステム管理者はデフォルトのドキュメントルート内のデータがアップグレードの間に触られないでいることを期待できない事を知っています。
サイトにとって致命的なファイルのためにデフォルトのドキュメントルートを使ってはいけません。デフォルトのドキュメントルートがシステムによって触られないでいるだろうという期待はできません。オペレーティングシステムのためにNGINXをアップデートおよびアップグレードする時にサイトにとって致命的なデータが失われえるかも知れない可能性はとても高いです。
BAD:
upstream {
server http://someserver;
}
server {
listen myhostname:80;
# [...]
}
listenディレクティブの中でホスト名を使うべきではありません。これは動作するかも知れませんが、ものすごく多くの問題が付いてきます。そのような問題の一つは、ホスト名は起動時あるいはサービスの再起動の間に解決されないかも知れないということです。これはNGINXが希望するTCPソケットにバイドできないようにするかも知れず、それはNGINXを全く起動できなくするでしょう。
安全な慣習は、ホスト名の変わりに結合されるべきIPアドレスを知り、そのアドレスを使うことです。これにより、NGINXはアドレスのルックアップをしなくて済み、外部および内部のリゾルバへの依存を取り除きます。
これと同じ問題はupstream locationにも適用されます。upstreamブロック内でホスト名を使うことを常に避けることはできないかも知れませんが、それは悪い慣習であり、問題を避けるために注意深い考慮を要求するでしょう。
GOOD:
upstream {
server http://10.48.41.12;
}
server {
listen 127.0.0.16:80;
# [...]
}
SSLv3のPOODLE 脆弱性のため、SSLを有効にしたサイトではSSLv3を使わないことをお勧めします。この行を使ってSSLv3をとても簡単に無効にすることができ、代わりにTLSプロトコルだけを提供します:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;