Nginx + PHP-FPM on FreeBSD

閒著沒事幹就嘗試把 Apache 2.2 搭配 PHP-FPM 的架構轉移至 Nginx。

根據維基百科,Nginx 是一個高效率、輕量的 HTTP 伺服器,在靜態檔案的效能相當好,不過若是有處理動態網頁 (像是 PHP) 的需求,則一般透過 FastCGI 的模式執行。先前我們已經建置了 Apache + mod_fcgid 搭配 PHP-FPM 的架構,因此在這次的轉移中我們只要把 Apache 換成 Nginx 即可。

首先就是安裝 Nginx。

cd /usr/ports/www/nginx && make install

安裝 PHP-FPM 與設定的部份就不在詳述了,可以找先前的文章參考。

Nginx 設定檔頗具彈性,換個說法就是不太容易撰寫,有許多小問題要注意。

user  www;
worker_processes  2;
events {
    worker_connections  1024;
}
# 設定 Worker 數量與其連接數

...

http {
    server {
        server_name localhost;
        root /usr/local/www/nginx;
        index index.htm index.html index.php;
        error_page 404 /404.html;

        location / {
            # 適用於 WordPress 的網址重導向規則,若是找不到就導回 index.php
            if (!-e $request_filename)
            {
                rewrite ^(.+)$ /index.php?q=$1 last;
            }
        }
        
        location ~* ^(.+\.php)(.*)$ {
            try_files $uri =404;
            # 解決 cgi.fix_pathinfo 可能造成的安全性問題
            # 例: img.gif/test.php 造成 img.gif 被當成 php 執行
            # 只有在 fastcgi 與 nginx 在同一台主機上適用
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param PATH_TRANSLATED $document_root/$fastcgi_path_info;
            fastcgi_pass   unix:/tmp/php-fpm.sock;
            # PHP-FPM 的 socket
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
        }

        location ~ /\.ht {
            deny  all;
            # 拒絕存取 apache 的 .htaccess 檔案
        }
    }
}

有些教學會將 root 與 index 放在 location / {…} 裡面,我發現如果要透過 FastCGI 執行的話,這樣的配置會造成路徑解析失敗,因此在我的設定檔中我把他們拿出來。

在上面提到了個資安問題,因為預設 Nginx 會將 .php 檔名結尾的東西全部交給 FastCGI 處理,但是 cgi.fix_pathinfo 這個參數會導致在常數傳遞的過程 PHP-FPM 會去修正不存在路徑,若是你在上傳資料夾上傳了個內含 PHP 程式碼的檔案並且命名為 test.gif,在瀏覽檔案的時候若是把網址變更為 http://localhost/upload/test.gif/sth.php ,會導致 test.gif 被執行。

要修復這個問題,可以透過設定 php.ini 中的 cgi.fix_pathinfo = 0  來關閉這個行為,或者如我設定檔所寫的,加入 try_files 與  fastcgi_split_path_info 來另外處理 PATH_INFO。

另外有個小問題,預設安裝的 Nginx FastCGI 參數檔裡面沒有定義 SCRIPT_FILENAME 這個變數,因此我們要把他加進去:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

 參考資料:

也谈Nginx的CGI PATH INFO问题
https://ihipop.info/2011/02/2118.html

 

Setting up PHP-FastCGI and nginx? Don’t trust the tutorials: check your configuration!
https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/

 

Nginx + PHP-FPM on FreeBSD

對「Nginx + PHP-FPM on FreeBSD」的想法

  1. 釣到一隻猴子@_@ 說:

    原來改NGINX這麼久了WWW
    (不過咱更閒 所以更早改了XDD)
    PATHINFO這問題的話
    用不到直接關了是最安全的www
    (不過頗明顯的 這網站本身就有用到了www)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料