不论是新老用户均可能掉进一样的陷阱里。下面咱们列举了觉的问题同时也给出了解决办法。在Freenode的IRC频道#nginx里,咱们常常遇到这类问题。javascript
这些常见问题,通常是因某人试图从别人的配置里直接拷贝后拿来用,并非全部拷贝的都有问题,惋惜的是,大部分都有问题。即便是Linode文档库里也存在因社区成员不去维护致使质量差的信息。php
这个文档由大量NGINX社区成员建立和审查,这个特殊文档的存在也是由于这些太过来常见了并常常发生。css
你可能并无找你跟你直接有关的特殊问题,也许咱们确实是没有指出你常常的特殊问题。但,不要觉得你来到这个页面是没有缘由的,你被带到这个页面至少表示你在下面的问题里遇到过问题:)html
永远不要使用777。不要觉得这只是一个漂亮的数字,即便在测试环境也代表你会没有线索查你正在作的事。你能够对整个路径的权限进行检查,能够考虑你正在作的事实。前端
要检查路径的权限,你能够:java
namei -om /path/to/check
劣:node
server { server_name www.example.com; location / { root /var/www/nginx-default/; # [...] } location /foo { root /var/www/nginx-default/; # [...] } location /bar { root /var/www/nginx-default/; # [...] } }
能够工做。每一个location块里都加上root指令没有错,也能很好的工做。那会有什么问题呢?若是某一个location块你路径写错了,将致使没有根目录。来看下什么是优的配置。nginx
优:正则表达式
server { server_name www.example.com; root /var/www/nginx-default/; location / { # [...] } location /foo { # [...] } location /bar { # [...] } }
劣:后端
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; # [...] } } }
为什么重复那么多没必要要的行?其实只要简单的使用index指令一次,只要在http{}里使用一次,下面的区块将自动继承。
优:
http { index index.php index.htm index.html; server { server_name www.example.com; location / { # [...] } } server { server_name example.com; location / { # [...] } location /foo { # [...] } } }
只有少数一些讨论if的文章,有篇叫 if是魔鬼 的你必定要看,下面举些列子说明为什么if如此坏。
劣:
server { server_name example.com *.example.com; if ($host ~* ^www\.(.+)) { set $raw_domain $1; rewrite ^/(.*)$ $raw_domain/$1 permanent; } # [...] } }
这里实际上有三个问题。首先看看if,也是咱们如今要关注的,为什么是劣的?你读过这篇文章 If是魔鬼 吗?当nginx接收到一个请求无论子域名是什么,即便是www.example.com或example.com,if指令也是每次都要调用,由于NGINX须要每次对请求头Host作处理,这特别没有效率,你要千万注意避免它。能够替换为两个server区块,以下面的列子:
优:
server { server_name www.example.com; return 301 $scheme://example.com$request_uri; } server { server_name example.com; # [...] }
这种配置也可使配置更好阅读,这种方法减小了NGINX的处理需求。咱们去除了谬误的if,同时咱们使用了$schema避免了硬编码URI,如http或https。
使用if来判断一个文件是否存在太可怕了。也就是说若是你有最新版的NGINx,使用tryfiles指令将更加容易。
劣:
server { root /var/www/example.com; location / { if (!-f $request_filename) { break; } } }
优:
server { root /var/www/example.com; location / { try_files $uri $uri/ /index.html; } }
咱们只是修改了判断文件是否存在但又不使用if指令,使用tryfiles表示能够测试一系列文件,若是$uri不存在,再试$uri/,若是还不存在,就使用默认位置(index.html)。
在这个列子,若是$uri存在就使用它,若是不存在,再判断$uri/目录是否存在,若是不存在就使用index.html,必需要保证最后一个检测的文件存在。很简单吧!下面是另外一个例子去掉if指令。
"前端控制模式"-Front controller patterm在php开源界很是流行,但大都使用的比较复杂,如Drupal、jammla等,只要像这样:
try_files $uri $uri/ /index.php?q=$uri&$args;
注意-参数根据你使用的开源软件不一样而不一样。如:
有些软件甚至不须要查询参数而是用REQUEST_URI参数,如,Wordpress支持这个:
try_files $uri $uri/ /index.php;
若是你不关心检查目录,只要去掉$uri/。
固然,你可能遇到些特殊状况,须要更复杂的配置,但对通常站点,这些就够了。
不少NGINX+PHP的配置会传递全部以.php结尾的请求给php,但这里会出现一个严重的安全问题,可能致使精心构造的代码被执行。
这类问题看起来如:
location ~* \.php$ { fastcgi_pass backend; # [...] }
这里,每一个以.php结尾的请求将传递给FastCGI后端。这会致使一个问题,PHP的默认配置对于找不到的文件,会对整个请求文件路径猜想哪一个部分须要执行。
举例,若是请求是/forum/avatar/1232.jpg/file.php,文件并不存在,但/forum/avatar/1232.jpg存在,则php也会执行1232.jpg,若是1232.jpg包含php代码,也会被执行。
避免执行的选项有:
cgi.fixpathinfo=0.这会致使php不尝试字面上的路径,若是文件没找到就中止处理。
保证NGINX只传递特定文件给PHP
location ~* (file_a|file_b|file_c)\.php$ { fastcgi_pass backend; # [...] }
指定用户上传的目录不能够执行php
location /uploaddir { location ~ \.php$ {return 403;} # [...] }
使用tryfles指令过滤有问题的条件
location ~* \.php$ { try_files $uri =404; fastcgi_pass backend; # [...] }
使用嵌套location过滤
location ~* \.php$ { location ~ \..*/.*\.php$ {return 404;} fastcgi_pass backend; # [...] }
脚本文件中的FastCGI路径
太多例子说用绝对路径来指定路径的错误作法。一般见于php配置块。当你从svn中安装NGINX,一般会有include fastcgiparams;在你的配置中,目录通常在/etc/nginx。
优:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
劣:
fastcgi_param SCRIPT_FILENAME /var/www/yoursite.com/$fastcgi_script_name;
$docmentroot在哪设的?一般是在你的server块里,不在?看看上面的第一个坑。
在这不要犯糊,很容易被正则表达式搞蒙,事实上,很简单,只要努力作到足够简单就行。
劣:
rewrite ^/(.*)$ http://example.com/$1 permanent;
优:
rewrite ^ http://example.com$request_uri? permanent;
更优:
return 301 http://example.com$request_uri;
看看上面的例子,第一个规则是获取所有url而后减fcfu最一个反斜杆,事实上使用内置变量$request_uri能够更简单。
很是简单,rewrites规则都是相对路径,除非你告诉NGINX不是,使用rewrite的绝对路径也很简单,添加一个schema。
劣:
rewrite ^ example.com permanent;
优:
rewrite ^ http://example.com permanent;
上面的例子中只是添加了http://,简单而有效。
劣:
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; } }
恶心。这个例子中,什么内容都代理给了PHP,为何?Apache也许用来替代,但不必。try_files指令神奇的地方是:它按必定的顺序尝试使用文件。NGINX能够首先尝试静态文件,若是没有,继续尝试。意思是PHP不必定要处理全部文件。速度将更快!例如你有个1M的图片比较下经过用PHP来处理和用服务器直接处理的速度。看看优化后的方案:
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; } }
一样也是好的方案
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; } }
很容易不是吗?若是请求的URI存在,NGINX能够直接处理,若是不存在,若是是个目录也能够处理,若是还不是,再传递给代理。仅当NGINX不能处理时才传递给代理。
考虑下你的多少内容是静态的(图片、css、javascript等),可能能节省下大量的消耗。
浏览器缓存的问题。你的配置也许很完善但也有撞墙的时候。出现问题的缘由就是浏览器缓存。当下载页面时,浏览器会作缓存,同时也保存了文件怎么更新,若是你在测试 types{}指令,你可能须要经过如下方法来清缓存
若是nginx工做不正常多是由于sendfile指令,只要注释掉再试下。
若是你没有设置underscores_in_headers on;指令,NGINX将把包括下划线的头信息丢掉(依据http标准),这也是为了一种保护机制,防止异常的头信息与CGI变量冲突。
全部系统都有些不能使用的目录,如/和root,永远不要设置成document root目录。通常都是放在/var/www或/srv或/usr/share/www/。
不要使用系统安装包默认的DocumentRoot目录,由于软件升级或从新安装时,有可能修改该目录,若是你的业务恰好在使用这个目录,oops,目录有可能被删除并安装它的默认文件。当心。
劣:
upstream { server http://someserver; }
优:
server { listen myhostname:80; # [...] }
永远不要在listen指令中使用主机名。虽然能够工做,但会带来不少问题,一个是系统启动或service启动时hostname不必定能解析,这将致使nginx不能绑定到指令的tcp socket并启动失败。
安全的作法是指令ip地址来代替主机名。避免了域名解析的成本。同理,在upstream也同样,尽可能避免使用主机名。
优:
upstream { server http://10.48.41.12; }
注:多虚拟主机名时仍是避免不了。
SSLv3由于有安全风险,建议不要使用,而用TLS代替。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
翻译 朱淦<350050183@qq.com> 2016.7.20