閒著沒事幹就嘗試把 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這麼久了WWW
(不過咱更閒 所以更早改了XDD)
PATHINFO這問題的話
用不到直接關了是最安全的www
(不過頗明顯的 這網站本身就有用到了www)