閒著沒事幹就嘗試把 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)