Nginx完美配置,以及简要解释说明

2024年4月10日系统运维评论34,207字数 4207阅读14分1秒阅读模式

本文转载自:海滨擎蟹

仅供个人留档,未取得授权,侵删

Nginx 配置详情

server {
    listen       80;
    server_name  thinkphp.lo;
    root /var/www;
    index  index.html index.htm index.php;
    error_page  404              /404.html;
    location = /404.html {
        return 404 'Sorry, File not Found!';
    }
    error_page  500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html; # windows用户替换这个目录
    }
    location / {
        try_files $uri @rewrite;
    }
    location @rewrite {
        set $static 0;
        if  ($uri ~ \.(css|js|jpg|jpeg|png|gif|ico|woff|eot|svg|css\.map|min\.map)$) {
            set $static 1;
        }
        if ($static = 0) {
            rewrite ^/(.*)$ /index.php?s=/$1;
        }
    }
    location ~ /Uploads/.*\.php$ {
        deny all;
    }
    location ~ \.php/ {
       if ($request_uri ~ ^(.+\.php)(/.+?)($|\?)) { }
       fastcgi_pass 127.0.0.1:9000;
       include fastcgi_params;
       fastcgi_param SCRIPT_NAME     $1;
       fastcgi_param PATH_INFO       $2;
       fastcgi_param SCRIPT_FILENAME $document_root$1;
    }
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    location ~ /\.ht {
        deny  all;
    }
}

Nginx 配置详情 转自:老朱亲自写的,最完美ThinkPHP Nginx 配置文件 - ThinkPHP 框架

我们把内容拆分一下:

    listen       80;
    server_name  thinkphp.lo;
    root /var/www;
    index  index.html index.htm index.php; 

这部分是 Nginx 下所有的虚拟主机都要求存在的。

摘抄一个 nginx.conf 内推荐的简单配置:

    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

一点差别在于根目录和索引文件配置项的位置,后者把他们放到 location / {} 中,其实没多大差别。后面摘抄的简单配置在不需要 PHP 参与(简单 html 静态页面)的情况下直接就可以用了。

    error_page  404              /404.html;
    location = /404.html {
        return 404 'Sorry, File not Found!';
    }
    error_page  500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html; # windows用户替换这个目录
    }

这部分属于错误页面定义,对常见的 404、50x 错误,选择自定义错误页面,而不是展示服务器默认的页面。

    location ~ /Uploads/.*\.php$ {
        deny all;
    }
    ...
    location ~ /\.ht {
        deny  all;
    }

这部分也很好理解(大部分规则都会应用到具体访问路径或文件上,所以一般都是 location 加上定义的配置规则,然后内部是匹配规则的请求处理),就是当访问 Uploads 下的 php 文件时,拒绝访问(防止上传了恶意脚本然后被执行),后面就是禁止访问 htaccess 文件(猜的)。

解析到了这里,剩下的都是核心部分了。核心部分主要分成两部分:URL 重写部分和 php 脚本解析部分。

URL 重写

    location / {
        try_files $uri @rewrite;
    }
    location @rewrite {
        set $static 0;
        if  ($uri ~ \.(css|js|jpg|jpeg|png|gif|ico|woff|eot|svg|css\.map|min\.map)$) {
            set $static 1;
        }
        if ($static = 0) {
            rewrite ^/(.*)$ /index.php?s=/$1;
        }
    }

这部分前面的很像一种格式 try_files $uri $uri/ /index.php$uri;。只不过因为内容较多,把重写部分放在了 {} 内部。尝试解读,就是如果 uri 部分包含 css|js|... 等后缀,即请求这些类型的文件时,不执行重写。或者反过来说,如果不是请求这些具体的资源文件时,就执行 URL 重写。

等等,我好想还见过另外一种写法的改写:

location / {
    if (!-e $request_filename) {
         rewrite ^(.*)$ /index.php?s=/$1 last;
         #rewrite ^/(.*)$ /index.php/$1 last;
         #break;
    }
}

其实这两者效果一样的,只不过低版本的 nginx (具体低到什么版本我也不清楚)不支持 try_files 规则。

那么重写规则,到底重写了什么呢?这是关键。这就得说说 TP 框架的四种模式了(最新版本 TP 取消了普通模式,所以只剩下三种)

这些模式主要针对的是 TP 路由传递的方式来讲的,简单来讲,就是模块、控制器、方法名的传递方式。

普通模式
使用正常的 query_string 参数来传递路由信息。示例:http://域名/项目名/入口文件?m=模块名&a=方法名&键1=值1&键2=值2

PATHINFO 模式
使用 PATHINFO 虚拟路径来传递路由信息。示例:http://域名/项目名/入口文件/模块名/方法名/键1/值1/键2/值2

REWRITE 重写模式
在 PATHINFO 模式的基础上,去掉入口文件便于 SEO 优化。示例:http://域名/项目名/模块名/方法名/键1/值1/键2/值2

兼容模式
TP 框架自带的一种模式,主要兼容服务器不支持 PATHINFO、虚拟主机也不能自定义配置的情况。示例:http://域名/项目名/入口文件?s=模块名/方法名/键1/值1/键2/值2。可以看出来,与 PATHINFO 模式的主要区别在于 PATHINFO 部分的传入方式。本来如果服务器支持 PATHINFO 解析,或者可以自定义虚拟主机配置 PATHINFO 参数是没有问题,但如果这两种情况都不能满足的话,又想使用形似 PATHINFO 模式传递路由信息和其他参数,就将 PATHINFO 部分通过参数 s 传入框架,框架会自动识别参数的。

除了普通模式和框架自带的兼容模式以外,要实现其他两种模式都需要借助服务器的额外配置。

就 PATHINFO 模式而言,关键点在于服务器是否支持 PATHINFO 模式,如果支持的话(php.ini 中 cgi.fix_pathinfo 项设为 1),服务器会自动解析出 URL 中的 PATHINFO 部分内容,并将它放到 $_SERVER['pathinfo'] 参数中。官方文档里说关闭 PATHINFO 模式可以 当文件不存在时,阻止 Ng­inx 将请求发送到后端的 PHP-FPM 模块,从而避免恶意脚本注入的攻击。所以对于可能没有开启 PATHINFO 的情况,又有通过 fastcgi_split_path_info 来分离 pathinfo 参数的配置方法。

具体分离方法如下(一般放在 php 脚本解析部分):

    #设置PATH_INFO,注意fastcgi_split_path_info已经自动改写了fastcgi_script_name变量,
    #后面不需要再改写SCRIPT_FILENAME,SCRIPT_NAME环境变量,所以必须在加载fastcgi.conf之前设置
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;

而在这个基础上的 REWRITE 重写模式,就是将 URL 中省略的入口文件 index.php 重写到 URL 中。

rewrite ^/(.*)$ /index.php/$1 last;

但如果服务器不支持 PATHINFO 模式,而自己去改写虚拟主机配置又太麻烦,或者一直调试不好的话(我经历过这样的情况),可以采用重写方式使用兼容模式。如下:

rewrite ^(.*)$ /index.php?s=/$1 last;

php 脚本解析

    location ~ \.php/ {
       if ($request_uri ~ ^(.+\.php)(/.+?)($|\?)) { }
       fastcgi_pass 127.0.0.1:9000;
       include fastcgi_params;
       fastcgi_param SCRIPT_NAME     $1;
       fastcgi_param PATH_INFO       $2;
       fastcgi_param SCRIPT_FILENAME $document_root$1;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

为什么会有两组针对 php 脚本解析的内容?其实这两组配置是不一样的,前者是针对有 PATHINFO 部分内容的 URL,解析内部的 PATHINFO;后者是针对访问内容只到入口文件没有 PATHINFO 的情况,这样直接解析就好。

有时我们也会定义错误日志文件和访问日志文件,一般放在 server 配置内部的末尾,如下:

    error_log  /var/log/nginx/ci.error.log;
    access_log  /var/log/nginx/ci.access.log;

Apache虚拟主机配置文件httpd.conf详解 前端开发

Apache虚拟主机配置文件httpd.conf详解

教程是在本地Windows系统上,使用XAMPP搭建的服务器环境做的示范。 原理都是类似的,不管是Nginx或者Linux服务器,都可以参考这个进行修改。 搭建了服务器环境,上线了网站,却发现默认地址...
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定