Tommy 碎碎念
https://blog.teatime.com.tw/
Tommy Wu's blog
tommy
2024-03-19T12:50:22Z
-
讓 Nginx 的 real_ip 模組找不到對應的 header 時, 使用 proxy protocol 傳入的 IP
https://blog.teatime.com.tw/1/post/493
<p>最近把 DNS 轉到 <a href="https://www.cloudflare.com/" target="_blank" rel="noopener">Cloudflare</a> 使用, 原本在主機上使用 <a href="https://www.haproxy.org/" target="_blank" rel="noopener">HAProxy</a> 把 SSL 的封包轉到個別對應的軟體是使用 Proxy Protocol 將來源 IP 通知處理的軟體. 在改用 Cloudflare 之後, 這個 IP 就變成 Cloudflare 的 IP 了. 這個在需要知道來源 IP 的軟體上, 就反而造成問題.</p>
<p>通常會走 Cloudflare 進來的, 也都是網頁的服務 (其他同樣使用 SSL 走 443 的服務, 也不需要透過 Cloudflare 處理, 通常可以在 DNS 上另外設定來避開). 依據 Cloudflare 的作法, 是應該使用 HTTP 的 header CF-Connecting-IP 來取得真實的來源 IP. 不過.... 由於我這邊是先透過 HAProxy 處理過, 混雜了來自 Cloudflare 與沒經過 Cloudflare 的封包 (例如內部網路的機器), 這時, 就變成使用 CF-Connecting-IP 時, 非來自 Cloudflare 的 IP 變成 HAProxy 的 127.0.0.1, 如果使用 Proxy Protocol 時, 那些透過 Cloudflare 的封包, 來源 IP 又全變成 Cloudflare 的 IP 了.</p>
<p>看了一下 <a href="https://nginx.org/" target="_blank" rel="noopener">Nginx</a> 的 real_ip 模組設定, <a href="http://nginx.org/en/docs/http/ngx_http_realip_module.html" target="_blank" rel="noopener">real_ip_header</a> 就只能設定一種, 不能有多重的設定, 所以就只好看一下 source, 自己動手來修改.</p>
<pre class="language-diff"><code>--- nginx-1.23.3/src/http/modules/ngx_http_realip_module.c.orig 2023-03-19 11:18:38.033783262 +0800
+++ nginx-1.23.3/src/http/modules/ngx_http_realip_module.c 2023-03-19 11:17:30.029338872 +0800
@@ -157,7 +157,8 @@
case NGX_HTTP_REALIP_XREALIP:
if (r->headers_in.x_real_ip == NULL) {
- return NGX_DECLINED;
+ //return NGX_DECLINED;
+ goto try_proxy_protocol;
}
value = &r->headers_in.x_real_ip->value;
@@ -170,7 +171,8 @@
xfwd = r->headers_in.x_forwarded_for;
if (xfwd == NULL) {
- return NGX_DECLINED;
+ //return NGX_DECLINED;
+ goto try_proxy_protocol;
}
value = NULL;
@@ -178,6 +180,7 @@
break;
case NGX_HTTP_REALIP_PROXY:
+try_proxy_protocol:
if (r->connection->proxy_protocol == NULL) {
return NGX_DECLINED;
}
@@ -219,7 +222,8 @@
}
}
- return NGX_DECLINED;
+ //return NGX_DECLINED;
+ goto try_proxy_protocol;
}
found:
</code></pre>
<p>修改的方式其實不難, 這邊的處理雖然是用 switch case 來獨立處理, 不過可以發現其實是不是透過 Proxy Protocol 處理過, 是有方法可以判斷的, 所以我們只要在其中每一種用來取得 real_ip 的 case 中, 如果最後沒有處理到, 就轉給 Proxy Protocol 那一段來處理就可以.</p>
<p>這樣子修改後, 我們依舊可以在 Nginx 中設定</p>
<pre class="language-nginx"><code>real_ip_header CF-Connecting-IP;</code></pre>
<p>就算是沒有這個 header 的來源, 一樣仍透過 Proxy Protocol 處理, 就算也沒透過 Proxy Protocol, 一樣可以判斷出來而不會造成問題.</p>
Linux
Patch
Nginx
2023-03-24T10:08:25Z
tommy
-
Let's Encrypt
https://blog.teatime.com.tw/1/post/477
<p>以往 SSL 憑證都要花錢買, 當然... 也可以自己用 openssl 來產生, 不過.... 自己做的 rootca 並不會被其他人承認, 常常要自己匯入後才能正常使用. 不過... 這情形在 <a href="https://letsencrypt.org/" target="_blank">Let's Encrypt</a> 出現後, 大家都可以申請免費的 SSL 憑證了, 雖然期限只有三個月, 不過.... 只要到期前記得去 renew 就可以一直用下去.</p><p>官方的 client 用起來不怎麼簡單.... 通常用 <a href="https://github.com/lukas2511/letsencrypt.sh" target="_blank">letencrypt.sh</a> 會比較容易. 有人也寫了 <a href="https://letsencrypt.tw/" target="_blank">letencrypt.sh 的中文說明</a>, 可以參考看看. 要注意的是文章提到的 config.sh 在目前的版本來看, 應該是 config 才對.</p><p>我目前只用 nginx, 所以就說一下在 nginix 的作法.</p><p>Let's Encrypt 的驗證方法是 http-01 (目前也支援 dns-01, 不然看不太懂, 加上... 申請這個通常是給 http 使用, 所以直接用 http-01 的方式比較快). 這個方式在驗證時, 需要在申請的 domain 下頭的 web server (只能用 port 80, 可以轉址, 但入口只能是標準的 http port 80) 的 /.well-known/acme-challenge/ 目錄下, 產生一個亂數的網址的檔案, 然後 Let's Encrypt 在簽署時會連過來抓取這個檔案, 如果裡頭的內容正確, 就算通過驗證, 就會簽發對應的憑證.</p><p>在 nginx 上頭, 可以用 location 指令搭配 alias 來處理:</p><pre class="apache"><div class="insertcode">location /.well-known/acme-challenge/ {<br /> <span>alias</span> /var/www/letsencrypt/;<br />}</div></pre><p>不過... 在我的機器上, 不知那個設定有衝突... 反正上頭的設定不會正常運作. 所以... 我就改成:</p><pre class="apache"><div class="insertcode">location ~ ^/.well-known/acme-challenge/(.*)$ {<br /> <span>alias</span> /var/www/letsencrypt/$1;<br />}</div></pre><p>建議設定好後, 自己在這目錄下建一個 test.txt, 然後連過去抓看看能不能正常抓到. (每個要用的 domain 下的虛擬網站都要能用) </p><p>然後就可以把這些 domain name 寫到 letencrypt.sh 所在目錄下的 domains.txt (建議用 domains.txt 處理, 用參數只能一次簽一個 domain name), 內容像是:</p><pre class="ini"><div class="insertcode">teatime.com.tw www.teatime.com.tw blog.teatime.com.tw<br />abc.com www.abc.com<br />xzy.org</div></pre><p>每行是一個憑證, 同一個憑證可以允許多個網站 (要同一個 domain), letsencrypt.sh 會產生在其目錄下的 certs 子目錄內, 每個憑證一個目錄, 用該行的第一個名稱當目錄名稱.</p><p>直接執行 letsencrypt.sh -c 就會可以了 (renew 使用同樣指令, 會檢查是否需要才真的去 renew).</p><p>如果一切正常, 會有 cert.pem, chain.pem, fullchain.pem privkey.pem 在每個憑證的目錄下. 通常我們是用 fullchain.pem 與 privkey.pem 就可以.</p><p>nginx:</p><pre class="apache"><div class="insertcode">server {<br /> <span>listen</span> <span>443</span> ssl http2;<br /> server_name www.teatime.com.tw teatime.com.tw;<br /> <br /> ssl_certificate /etc/letsencrypt.sh/certs/teatime.com.tw/fullchain.pem;<br /> ssl_certificate_key /etc/letsencrypt.sh/certs/teatime.com.tw/privkey.pem;<br />}</div></pre><p>如果要用 Strong Diffie-Hellman Group, 可以自己用 openssl 產生:</p><pre class="bash"><div class="insertcode">openssl dhparam <span>-out</span> <span>/</span>etc<span>/</span>ssl<span>/</span>certs<span>/</span>dhparam.pem <span>2048</span></div></pre><p>然後在 nginx 上頭設定:</p><pre class="apache"><div class="insertcode">server {<br /> <span>listen</span> <span>443</span> ssl http2;<br /> server_name www.teatime.com.tw teatime.com.tw;<br /> <br /> ssl_certificate /etc/letsencrypt.sh/certs/teatime.com.tw/fullchain.pem;<br /> ssl_certificate_key /etc/letsencrypt.sh/certs/teatime.com.tw/privkey.pem;<br /> <br /> ssl_protocols TLSv1 TLSv1.1 TLSv1.2;<br /> ssl_prefer_server_ciphers <span>on</span>;<br /> ssl_dhparam /etc/ssl/certs/dhparam.pem;<br /> ssl_ciphers <span>'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'</span>;<br /> ssl_session_timeout 1d;<br /> ssl_session_cache shared:SSL:50m;<br /> ssl_stapling <span>on</span>;<br /> ssl_stapling_verify <span>on</span>;<br /> add_header Strict-Transport-Security max-age=<span>15768000</span>;<br />}</div></pre><p>postfix 也可以用:</p><pre class="ini"><div class="insertcode"><span>smtpd_tls_cert_file</span> <span>=</span><span> /etc/letsencrypt.sh/certs/teatime.com.tw/fullchain.pem</span><br /><span>smtpd_tls_key_file</span> <span>=</span><span> /etc/letsencrypt.sh/certs/teatime.com.tw/privkey.pem</span><br /><span>smtpd_use_tls</span> <span>=</span><span> yes</span><br /><span>smtpd_tls_auth_only</span> <span>=</span><span> no</span><br /><span>tls_random_source</span> <span>=</span><span> dev:/dev/urandom</span></div></pre><p>dovecot 也可以用:</p><pre class="ini"><div class="insertcode"><span>ssl</span> <span>=</span><span> yes</span><br /><span>ssl_cert</span> <span>=</span><span> </etc/letsencrypt.sh/certs/teatime.com.tw/fullchain.pem</span><br /><span>ssl_key</span> <span>=</span><span> </etc/letsencrypt.sh/certs/teatime.com.tw/privkey.pem</span></div></pre><p>squid 如果有編入 ssl 支援, 要做 http over https 的話, 需要把 privkey.pem 與 fullchain.pem 合併成一個檔案:</p><pre class="bash"><div class="insertcode"><span>cat</span> privkey.pem fullchain.pem <span>></span> both.pem</div></pre><p>然後在 squid.conf 設定:</p><pre class="ini"><div class="insertcode">https_port <span>8443</span> cert<span>=</span><span>/etc/letsencrypt.sh/certs/teatime.com.tw/both.pem</span><br /></div></pre><p>如果是 pure-ftpd 的話... 是可以使用上頭這個 both.pem, 只不過... pure-ftpd 沒有地方指定, 只會抓 /etc/ssl/private/pure-ftpd.pem 這個檔案... 所以.. 直接做一個 symlink 過去就可以.</p><p>原則上, 這樣子處理後, 就可以正確使用 Let's Encrypt 的憑證了.</p><p>每次憑證是 3 個月, 所以... 可以每個星期執行一次 letencrypt.sh -c 就會在過期前自動 renew 了. 當然... 如果 renew 之後, 上面那些程式並不會自動載入新的憑證, 所以要寫個小 script 去檢查是不是檔案有變, 有的話要去 reload 這些 service (pure-ftpd 只能 restart 才有用).</p>
Nginx
2016-05-25T22:06:47Z
tommy
-
奇怪的 nginx segfault 錯誤
https://blog.teatime.com.tw/1/post/416
<p>這幾個星期發現家裡的 <a href="http://nginx.org/" target="_blank">nginx</a> 在隔約 2 小時左右 (間隔不一定, 有時很久沒出現, 有時連續出現, 不過多數看起來是隔兩小時出現一次), 就會出現一次 segfault, 雖然只是其中一個 worker, 也會被重新執行, 並不會影響到實際的 web server 運作, 不過.. 在 log 裡常常看到這個錯誤也很奇怪.</p><p>試著在 <a href="http://wiki.nginx.org/CoreModule#error_log" target="_blank">error_log</a> 中加上 <a href="http://nginx.org/en/docs/debugging_log.html" target="_blank">debug</a> 參數, 不過除了 log 變大之外, 出現 segfault 的那時間, 並沒有任何的 log 產生 (來不及寫出就當了? 還是還沒寫 log 就當了?) , 所以也看不出來是什麼原因.</p><p>加上些<a href="http://wiki.nginx.org/Debugging" target="_blank">設定, 產生 coredump file </a> 之後, 可以知道問題都是發生在 src/http/modules/ngx_http_index_module.c 裡頭的 ngx_http_index_handler() 一開始的地方所產生的. 試著加上一些 log, 不過... 透過 nginx 的 log function 來寫出, 似乎都沒有真的寫入到 log (是我用錯了嗎?), 最後乾脆自己用一般的 C stdio 來處理, 直接寫到 /tmp 的某個檔案去. 終於發現 segfault 產生時, r->uri.len 的值是 0, 導致一開始 -1後去讀取的位址不合法.</p><p>不過想不出為什麼會有長度是 0 的 uri 這種 request, 不知道怎麼由源頭處理, 所以就直接治標.... 檢查是 0 就直接回錯誤, 不再去處理. 這樣子做之後, 用了三天, 應該是解決這個問題了, 至少是沒看到 segfault 的錯誤了.</p><p>修正方式如下:</p><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff -Nur nginx-1.0.12.orig/src/http/modules/ngx_http_autoindex_module.c nginx-1.0.12/src/http/modules/ngx_http_autoindex_module.c<br /><span class="re3">--- nginx-1.0.12.orig/src/http/modules/ngx_http_autoindex_module.c <span class="nu0">2012</span>-02-06 04:02:<span class="nu0">59.000000000</span> +0800</span><br /><span class="re4">+++ nginx-1.0.12/src/http/modules/ngx_http_autoindex_module.c <span class="nu0">2012</span>-02-<span class="nu0">10</span> <span class="nu0">20</span>:01:<span class="nu0">54.719060672</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">157</span>,<span class="nu0">6</span> +<span class="nu0">157</span>,<span class="nu0">10</span> @@</span><br /> static char *months<span class="br0">[</span><span class="br0">]</span> = <span class="br0">{</span> "Jan", "Feb", "Mar", "Apr", "May", "Jun",<br /> "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" <span class="br0">}</span>;<br /> <br /><span class="re8">+ // twu2 begin, try to avoid segfault</span><br /><span class="re8">+ if <span class="br0">(</span>r == NULL || r->uri.len == <span class="nu0">0</span><span class="br0">)</span></span><br /><span class="re8">+ return NGX_HTTP_BAD_REQUEST;</span><br /><span class="re8">+ // twu2 end</span><br /> if <span class="br0">(</span>r->uri.data<span class="br0">[</span>r->uri.len - 1<span class="br0">]</span> != '/'<span class="br0">)</span> <span class="br0">{</span><br /> return NGX_DECLINED;<br /> <span class="br0">}</span><br />diff -Nur nginx-1.0.12.orig/src/http/modules/ngx_http_index_module.c nginx-1.0.12/src/http/modules/ngx_http_index_module.c<br /><span class="re3">--- nginx-1.0.12.orig/src/http/modules/ngx_http_index_module.c <span class="nu0">2012</span>-02-06 04:02:<span class="nu0">59.000000000</span> +0800</span><br /><span class="re4">+++ nginx-1.0.12/src/http/modules/ngx_http_index_module.c <span class="nu0">2012</span>-02-<span class="nu0">10</span> <span class="nu0">20</span>:01:<span class="nu0">15.615399122</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">109</span>,<span class="nu0">6</span> +<span class="nu0">109</span>,<span class="nu0">10</span> @@</span><br /> ngx_http_index_loc_conf_t *ilcf;<br /> ngx_http_script_len_code_pt lcode;<br /> <br /><span class="re8">+ // twu2 begin, try to avoid segfault</span><br /><span class="re8">+ if <span class="br0">(</span>r == NULL || r->uri.len == <span class="nu0">0</span><span class="br0">)</span></span><br /><span class="re8">+ return NGX_HTTP_BAD_REQUEST;</span><br /><span class="re8">+ // twu2 end</span><br /> if <span class="br0">(</span>r->uri.data<span class="br0">[</span>r->uri.len - 1<span class="br0">]</span> != '/'<span class="br0">)</span> <span class="br0">{</span><br /> return NGX_DECLINED;<br /> <span class="br0">}</span><br />diff -Nur nginx-1.0.12.orig/src/http/modules/ngx_http_random_index_module.c nginx-1.0.12/src/http/modules/ngx_http_random_index_module.c<br /><span class="re3">--- nginx-1.0.12.orig/src/http/modules/ngx_http_random_index_module.c <span class="nu0">2012</span>-02-06 04:02:<span class="nu0">59.000000000</span> +0800</span><br /><span class="re4">+++ nginx-1.0.12/src/http/modules/ngx_http_random_index_module.c <span class="nu0">2012</span>-02-<span class="nu0">10</span> <span class="nu0">20</span>:02:<span class="nu0">04.065805793</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">83</span>,<span class="nu0">6</span> +<span class="nu0">83</span>,<span class="nu0">10</span> @@</span><br /> ngx_array_t names;<br /> ngx_http_random_index_loc_conf_t *rlcf;<br /> <br /><span class="re8">+ // twu2 begin, try to avoid segfault</span><br /><span class="re8">+ if <span class="br0">(</span>r == NULL || r->uri.len == <span class="nu0">0</span><span class="br0">)</span></span><br /><span class="re8">+ return NGX_HTTP_BAD_REQUEST;</span><br /><span class="re8">+ // twu2 end</span><br /> if <span class="br0">(</span>r->uri.data<span class="br0">[</span>r->uri.len - 1<span class="br0">]</span> != '/'<span class="br0">)</span> <span class="br0">{</span><br /> return NGX_DECLINED;<br /> <span class="br0">}</span><br />diff -Nur nginx-1.0.12.orig/src/http/modules/ngx_http_static_module.c nginx-1.0.12/src/http/modules/ngx_http_static_module.c<br /><span class="re3">--- nginx-1.0.12.orig/src/http/modules/ngx_http_static_module.c <span class="nu0">2012</span>-02-06 04:02:<span class="nu0">59.000000000</span> +0800</span><br /><span class="re4">+++ nginx-1.0.12/src/http/modules/ngx_http_static_module.c <span class="nu0">2012</span>-02-<span class="nu0">10</span> <span class="nu0">20</span>:02:<span class="nu0">16.225907865</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">59</span>,<span class="nu0">6</span> +<span class="nu0">59</span>,<span class="nu0">10</span> @@</span><br /> ngx_open_file_info_t of;<br /> ngx_http_core_loc_conf_t *clcf;<br /> <br /><span class="re8">+ // twu2 begin, try to avoid segfault</span><br /><span class="re8">+ if <span class="br0">(</span>r == NULL || r->uri.len == <span class="nu0">0</span><span class="br0">)</span></span><br /><span class="re8">+ return NGX_HTTP_BAD_REQUEST;</span><br /><span class="re8">+ // twu2 end</span><br /> if <span class="br0">(</span>!<span class="br0">(</span>r->method & <span class="br0">(</span>NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><br /> return NGX_HTTP_NOT_ALLOWED;<br /> <span class="br0">}</span></pre></div></pre><p>由 log 中猜測, 可能是下列的 request 造成的:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">114.36.29.113 - - [<span class="nu0">11</span>/Feb/<span class="nu0">2012</span>:07:<span class="nu0">48</span>:<span class="nu0">59</span> +0800] <span class="st0">"cix<span class="es0">\x</span>92P%Z<span class="es0">\x</span>B8<span class="es0">\x</span>5CI'<span class="es0">\x</span>AF<span class="es0">\x</span>0B<span class="es0">\x</span>CD|}<span class="es0">\x</span>DB<span class="es0">\x</span>06<span class="es0">\x</span>CB<span class="es0">\x</span>14:<span class="es0">\x</span>05<span class="es0">\x</span>98<span class="es0">\x</span>EA<span class="es0">\x</span>86<span class="es0">\x</span>A1<span class="es0">\x</span>91 <span class="es0">\x</span>D0<span class="es0">\x</span>F88<span class="es0">\x</span>8A<span class="es0">\x</span>CC`<span class="es0">\x</span>C6"</span> <span class="nu0">400</span> <span class="nu0">173</span> <span class="st0">"-"</span> <span class="st0">"-"</span><br />188.134.92.205 - - [<span class="nu0">11</span>/Feb/<span class="nu0">2012</span>:09:<span class="nu0">49</span>:<span class="nu0">17</span> +0800] <span class="st0">"<span class="es0">\x</span>03<span class="es0">\x</span>E3y<span class="es0">\x</span>B4<span class="es0">\x</span>DD<span class="es0">\x</span>EE<span class="es0">\x</span>B0<span class="es0">\x</span>97<span class="es0">\x</span>CC?<span class="es0">\x</span>DD,<span class="es0">\x</span>BA<span class="es0">\x</span>B2ux{<span class="es0">\x</span>97<span class="es0">\x</span>BD<span class="es0">\x</span>D0<span class="es0">\x</span>DA <span class="es0">\x</span>B7g<span class="es0">\x</span>86?1<span class="es0">\x</span>B5<span class="es0">\x</span>B5<span class="es0">\x</span>98K<span class="es0">\x</span>8B<span class="es0">\x</span>BB<span class="es0">\x</span>1D<span class="es0">\x</span>09`<span class="es0">\x</span>B0"</span> <span class="nu0">400</span> <span class="nu0">173</span> <span class="st0">"-"</span> <span class="st0">"-"</span><br />99.125.248.167 - - [<span class="nu0">11</span>/Feb/<span class="nu0">2012</span>:<span class="nu0">11</span>:<span class="nu0">49</span>:<span class="nu0">36</span> +0800] <span class="st0">"<span class="es0">\x</span>C1<span class="es0">\x</span>F0<span class="es0">\x</span>15<span class="es0">\x</span>0B<span class="es0">\x</span>F6b<span class="es0">\x</span>9D<span class="es0">\x</span>02n<span class="es0">\x</span>F7<span class="es0">\x</span>E4<span class="es0">\x</span>C7<span class="es0">\x</span>D7<span class="es0">\x</span>D4N!<span class="es0">\x</span>B3E<span class="es0">\x</span>22<span class="es0">\x</span>BB<span class="es0">\x</span>FE<span class="es0">\x</span>84<span class="es0">\x</span>CFrX<span class="es0">\x</span>C0<span class="es0">\x</span>EEp<span class="es0">\x</span>06<span class="es0">\x</span>1F <span class="es0">\x</span>C7"</span> <span class="nu0">400</span> <span class="nu0">173</span> <span class="st0">"-"</span> <span class="st0">"-"</span><br />69.207.182.218 - - [<span class="nu0">11</span>/Feb/<span class="nu0">2012</span>:<span class="nu0">13</span>:<span class="nu0">49</span>:<span class="nu0">54</span> +0800] <span class="st0">"<span class="es0">\x</span>0C<span class="es0">\x</span>C7/<span class="es0">\x</span>F57<span class="es0">\x</span>DF<span class="es0">\x</span>5C<span class="es0">\x</span>9D<span class="es0">\x</span>CC<span class="es0">\x</span>AB;M<span class="es0">\x</span>D8O<span class="es0">\x</span>08~<span class="es0">\x</span>BCL<span class="es0">\x</span>02<span class="es0">\x</span>CD<span class="es0">\x</span>D7 b#<span class="es0">\x</span>88<span class="es0">\x</span>B9<span class="es0">\x</span>AB<span class="es0">\x</span>93<span class="es0">\x</span>E1<span class="es0">\x</span>A1<span class="es0">\x</span>D7<span class="es0">\x</span>8C<span class="es0">\x</span>1A<span class="es0">\x</span>DA<span class="es0">\x</span>92<span class="es0">\x</span>FA#<span class="es0">\x</span>A6q<span class="es0">\x</span>C3S<span class="es0">\x</span>CF"</span> <span class="nu0">400</span> <span class="nu0">173</span> <span class="st0">"-"</span> <span class="st0">"-"</span><br />94.159.209.183 - - [<span class="nu0">11</span>/Feb/<span class="nu0">2012</span>:<span class="nu0">15</span>:<span class="nu0">50</span>:<span class="nu0">13</span> +0800] <span class="st0">"<span class="es0">\x</span>94<span class="es0">\x</span>C9t<span class="es0">\x</span>E3<span class="es0">\x</span>05E<span class="es0">\x</span>DA<span class="es0">\x</span>B3<span class="es0">\x</span>DC)<span class="es0">\x</span>FC<span class="es0">\x</span>CA<span class="es0">\x</span>09<span class="es0">\x</span>B4s~<,<span class="es0">\x</span>18M<span class="es0">\x</span>AE<span class="es0">\x</span>D1<span class="es0">\x</span>19<span class="es0">\x</span>FAO|<span class="es0">\x</span>C2<span class="es0">\x</span>ECD<span class="es0">\x</span>06<span class="es0">\x</span>85<span class="es0">\x</span>0C<span class="es0">\x</span>8B<span class="es0">\x</span>F5<span class="es0">\x</span>8F<span class="es0">\x</span>8D<span class="es0">\x</span>AB<span class="es0">\x</span>C8<span class="es0">\x</span>EF<span class="es0">\x</span>ED<span class="es0">\x</span>12;<span class="es0">\x</span>F8<span class="es0">\x</span>94<span class="es0">\x</span>06<span class="es0">\x</span>8FV;><span class="es0">\x</span>F7<span class="es0">\x</span>08<span class="es0">\x</span>FB"</span> <span class="nu0">400</span> <span class="nu0">173</span> <span class="st0">"-"</span> <span class="st0">"-"</span></pre></div></pre><p>原本以為那些是中文, 不過用 utf-8 或 big5 來看, 都不是中文字, 是某個 web server 的 bug 嗎? 若是入侵的動作, 每隔兩小時才出現一次 (每次來源都不同), 也很奇怪. </p>
Patch
Nginx
2012-02-12T10:17:47Z
tommy
-
Nginx 對於 PHP 的錯誤轉向處理, fastcgi_intercept_errors 修正
https://blog.teatime.com.tw/1/post/402
<p>在一般靜態網頁的處理上頭, <a href="http://nginx.org/" target="_blank">nginx</a> 可以正常的顯示一些錯誤的訊息 (如 404 File not found 之類的訊息). 不過對於 <a href="http://www.php.net/" target="_blank">PHP</a> (其他用 fastcgi 方式跑的程式也一樣), 預設來說, 如果有什麼錯誤, 往往就看到空白的一個網頁. 而一般的 nginx 教學上頭, 對於這個問題的處理建議就是 <a href="http://wiki.nginx.org/HttpFcgiModule#fastcgi_intercept_errors" target="_blank">fastcgi_intercept_errors</a> on 的設定. 但... 這個方式並不是完美的.</p><p>首先在 fastcgi_intercept_errors off (預設值) 的情形下:</p><ul><li>如果 $uri 指到的那個 php 檔案不存在, nginx 會把這個檔案名轉給 php-fpm (或 cgi 程式) 去處理, 這時 PHP 會找不到該檔案, 會出現 No input file specified. 這個錯誤訊息. (http 的狀態碼是 404)</li><li>如果該 php 檔案存在, 但裡頭程式有問題 (打錯字之類), 如果 PHP 的 <a href="http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors" target="_blank">display_errors</a> 是 true, 會顯示 PHP 的錯誤訊息 (http 的狀態碼是 200, 對 nginx 來說, 就是不認為有發生錯誤). 如果 dispaly_errors 是 false 時, 則會出現完全空白的畫面 (http 的狀態碼是 500).</li><li>如果 php 的檔案沒有錯誤, 程式本身是正常的, 但對於程式的處理上頭, 要把這情形回應給使用者, 告知是不正常的狀態, 例如很多的程式, 在某些情形下會在找不到資料時, 顯示自訂的 404 網頁, 但是 http 的狀態碼是 404 (就是先執行 <a href="http://www.php.net/manual/es/function.header.php" target="_blank">header</a> ('HTTP/1.1 404 File Not Found'); 然後再顯示網頁的內容. 這時, 使用者會看到該程式所顯示的畫面, 但是 http 的狀態碼是 404. (不光是 404 的處理, 其它的也一樣)</li></ul><p>對正常的網頁管理來看, 第一種情形, 我們希望能看到的是系統給的 404 錯誤的網頁, 而不是 php 的訊息. 而第二種情形, 我們希望在 display_errors 關閉的情形下, 能顯示系統的 500 錯誤的網頁, 而不光只是一個空白畫面. 第三種情形就是我們正常所希望的處理方式了.</p><p>而一般在 ngnix 上, 為了解決前面兩個情形所碰到的問題, 建議是把 fastcgi_intercept_errors 設成 on (必須在有設定 <a href="http://wiki.nginx.org/HttpCoreModule#error_page" target="_blank">error_page</a> 的時候才有作用), 這時:</p><ul><li>一樣會把不存在的 php 檔名轉給 php-fpm 處理, 而 php-fpm 一樣會回 No input file specified. 這個錯誤訊息 (http 的狀態碼是 404), 但是 nginx 在取得 404 的狀態之後, 並不是顯示 No input file specified. 而是轉給 error_page 所指定的 404 處理網頁.</li><li>在 display_errors 打開的情形下, 不認為有錯誤, 而直接顯示 php 的錯誤訊息. 但是在 display_errors 關閉的情形下, 同樣得到沒有任何訊息的 http 狀態碼 500, 這時, nginx 會把這個錯誤再轉給 error_page 所指定的 500 處理網頁去處理.</li><li>nginx 雖然收到要顯示的網頁內容, 但是因為 http 狀態碼是 404, 所以並不直接顯示該內容, 而是轉到 error_page 的 404 處理網頁去顯示. (我的理解應該是這樣, 可是實際上, 是看到 browser 的 file not found 網頁, 而不是 nginx 那邊提供的內容) </li></ul><p>所以.... 為了解決前兩種情形的問題, 改用 fastcgi_intercept_errors on 之後, 前兩者是正常的, 但是第三種情形就反而不正常了, 與我們想要的內容不一樣.</p><p>對於第一種情形, 我們可以在 fastcgi_intercept_errors off 的情形下, 改用 <a href="http://wiki.nginx.org/HttpCoreModule#try_files" target="_blank">try_files</a> 或 <a href="http://wiki.nginx.org/HttpRewriteModule#if" target="_blank">if</a> 來檢查該 php 檔案是否存在, 這時, 就可以直接回應 404 的錯誤, 而不會到 php-fpm 處理才發現沒有該檔案. 利用這樣的檢查, 在不管 fastcgi_intercept_errors 的設定的情形下, 都可以轉到正確的 404 錯誤網頁. </p><p>所以, 問題就剩下第二種與第三種情形了.</p><p>就目前的 nginx 功能來看, 看來只能兩種選擇一種來用, 一個正常, 另一個就會不正常. 無法讓 fastcgi_intercept_errors 只去處理 404 以外的錯誤. 我們希望的功能, 應該是 fastcgi_intercept_errors on 的修正, 也就是在 fastcgi_intercept_errors 應該只處理 404 之外的錯誤, 不要再針對 404 去處理.</p><p>因為找不到其它的解決方法 (有人有不改程式的方法嗎?), 所以, 只好動手自己加上<a href="http://trac.nginx.org/nginx/ticket/71" target="_blank">這功能的修正</a>:</p><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff -Nur nginx-1.1.11.orig/src/http/modules/ngx_http_fastcgi_module.c nginx-1.1.11/src/http/modules/ngx_http_fastcgi_module.c<br /><span>--- nginx-1.1.11.orig/src/http/modules/ngx_http_fastcgi_module.c <span>2011</span>-<span>12</span>-09 <span>21</span>:<span>32</span>:<span>51.000000000</span> +0800</span><br /><span>+++ nginx-1.1.11/src/http/modules/ngx_http_fastcgi_module.c <span>2011</span>-<span>12</span>-<span>19</span> <span>13</span>:<span>52</span>:<span>43.431468931</span> +0800</span><br /><span>@@ -<span>287</span>,<span>6</span> +<span>287</span>,<span>16</span> @@</span><br /> offsetof<span>(</span>ngx_http_fastcgi_loc_conf_t, upstream.pass_request_body<span>)</span>,<br /> NULL <span>}</span>,<br /> <br /><span>+ // twu2 begin</span><br /><span>+ // option to skip <span>404</span> error</span><br /><span>+ <span>{</span> ngx_string<span>(</span>"fastcgi_intercept_error_skip_404"<span>)</span>,</span><br /><span>+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,</span><br /><span>+ ngx_conf_set_flag_slot,</span><br /><span>+ NGX_HTTP_LOC_CONF_OFFSET,</span><br /><span>+ offsetof<span>(</span>ngx_http_fastcgi_loc_conf_t, upstream.intercept_error_skip_404<span>)</span>,</span><br /><span>+ NULL <span>}</span>,</span><br /><span>+ // twu2 edn</span><br /><span>+</span><br /> <span>{</span> ngx_string<span>(</span>"fastcgi_intercept_errors"<span>)</span>,<br /> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,<br /> ngx_conf_set_flag_slot,<br /><span>@@ -<span>2092</span>,<span>6</span> +<span>2102</span>,<span>10</span> @@</span><br /> conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;<br /> <br /> conf->upstream.intercept_errors = NGX_CONF_UNSET;<br /><span>+ // twu2 begin</span><br /><span>+ // option to skip <span>404</span> error</span><br /><span>+ conf->upstream.intercept_error_skip_404 = NGX_CONF_UNSET;</span><br /><span>+ // twu2 end</span><br /> <br /> /* "fastcgi_cyclic_temp_file" is disabled */<br /> conf->upstream.cyclic_temp_file = <span>0</span>;<br /><span>@@ -<span>2332</span>,<span>6</span> +<span>2346</span>,<span>11</span> @@</span><br /> <br /> ngx_conf_merge_value<span>(</span>conf->upstream.intercept_errors,<br /> prev->upstream.intercept_errors, 0<span>)</span>;<br /><span>+ // twu2 begin</span><br /><span>+ // option to skip <span>404</span> error</span><br /><span>+ ngx_conf_merge_value<span>(</span>conf->upstream.intercept_errors,</span><br /><span>+ prev->upstream.intercept_errors, 0<span>)</span>;</span><br /><span>+ // twu2 end</span><br /> <br /> ngx_conf_merge_ptr_value<span>(</span>conf->catch_stderr, prev->catch_stderr, NULL<span>)</span>;<br /> <br />diff -Nur nginx-1.1.11.orig/src/http/ngx_http_upstream.c nginx-1.1.11/src/http/ngx_http_upstream.c<br /><span>--- nginx-1.1.11.orig/src/http/ngx_http_upstream.c <span>2011</span>-<span>12</span>-09 <span>21</span>:<span>19</span>:<span>57.000000000</span> +0800</span><br /><span>+++ nginx-1.1.11/src/http/ngx_http_upstream.c <span>2011</span>-<span>12</span>-<span>19</span> <span>13</span>:<span>49</span>:<span>21.476532705</span> +0800</span><br /><span>@@ -<span>1742</span>,<span>6</span> +<span>1742</span>,<span>12</span> @@</span><br /> return NGX_DECLINED;<br /> <span>}</span><br /> <br /><span>+ // twu2 begin</span><br /><span>+ // don't intercept <span>404</span> error <span>(</span>it will be processed by upstream<span>)</span></span><br /><span>+ if <span>(</span>status == NGX_HTTP_NOT_FOUND && u->conf->intercept_error_skip_404<span>)</span></span><br /><span>+ return NGX_DECLINED;</span><br /><span>+ // twu2 end</span><br /><span>+</span><br /> clcf = ngx_http_get_module_loc_conf<span>(</span>r, ngx_http_core_module<span>)</span>;<br /> <br /> if <span>(</span>clcf->error_pages == NULL<span>)</span> <span>{</span><br />diff -Nur nginx-1.1.11.orig/src/http/ngx_http_upstream.h nginx-1.1.11/src/http/ngx_http_upstream.h<br /><span>--- nginx-1.1.11.orig/src/http/ngx_http_upstream.h <span>2011</span>-<span>12</span>-09 <span>21</span>:<span>19</span>:<span>57.000000000</span> +0800</span><br /><span>+++ nginx-1.1.11/src/http/ngx_http_upstream.h <span>2011</span>-<span>12</span>-<span>19</span> <span>13</span>:<span>50</span>:<span>22.147014289</span> +0800</span><br /><span>@@ -<span>148</span>,<span>6</span> +<span>148</span>,<span>10</span> @@</span><br /> <br /> ngx_flag_t ignore_client_abort;<br /> ngx_flag_t intercept_errors;<br /><span>+ // twu2 begin</span><br /><span>+ // add an option to skip intercept <span>404</span> error</span><br /><span>+ ngx_flag_t intercept_error_skip_404;</span><br /><span>+ // twu2 end</span><br /> ngx_flag_t cyclic_temp_file;<br /> <br /> ngx_path_t *temp_path;</pre></div></pre><p>經過這個修正之後, 我們只要在 nginx.conf 中設定</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"> fastcgi_intercept_errors <span>on</span>;<br /> fastcgi_intercept_error_skip_404 <span>on</span>;</pre></div></pre><p>然後在 php 的處理之前加上檔案的存在檢查:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><strike>location ~ \.php$ {<br /> try_files $uri =<span>404</span>;</strike></pre></div></pre><p><strike>用 try_files 去檢查是否存在, 不存在就回傳 404.</strike></p><p>用 try_files 似乎會檢查不出來, 所以看來還是要用 if 來處理:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># without path_info</span><br />location ~ ^(?<SCRIPT_NAME>/.*\.(php|suphp))$ {<br /> if (!-f $document_root$SCRIPT_NAME) {<br /> return <span class="nu0">404</span>;<br /> }</pre></div></pre><p>在 userdir 上頭, 由於目錄會改寫, 直接用 try_files 會有問題, 可以改成這樣:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">location ~ ^/~(?<USER>.+?)(?<SCRIPT_NAME>/.+\.php)$ {<br /> root /home/$USER/public_html;<br /> if (!-f $document_root$SCRIPT_NAME) {<br /> return <span>404</span>;<br /> }</pre></div></pre><p>這樣子就可以達到我們要的功能了.</p><hr width="100%" size="2" /><p>補充一下, 上頭那個 php 的處理, 如果使用 try_files 在 PATH_INFO 的狀態時, 會造成 PATH_INFO 無法正常使用, 所以對於 PATH_FILE 的 php 處理, 要改成跟 userdir 一樣, 用 if 來處理才可以, 如:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># with path_info</span><br />location ~ ^(?<SCRIPT_NAME>/.*\.(php|suphp))(?<PATH_INFO>.*)$ {<br /> <span class="co1"># use try_files here will make PATH_INFO not work, so use if</span><br /> <span class="co1">#try_files $uri =404;</span><br /> if (!-f $document_root$SCRIPT_NAME) {<br /> return <span class="nu0">404</span>;<br /> }</pre></div></pre><p>改成這樣, 有用到 PATH_INFO 的程式就正常了. </p>
PHP
Nginx
2011-12-19T17:54:06Z
tommy
-
Gallery 3 在 Nginx 下的安裝與設定
https://blog.teatime.com.tw/1/post/390
<p>由於 <a href="http://gallery.menalto.com/" target="_blank">Gallery</a> 3 大幅的簡化, 所以在安裝使用上, 並不像 Gallery 2 一樣有那麼多的 rewrite 要處理, 相對來說是簡單許多. 原則上只要 <a href="http://nginx.org/" target="_blank">nginix</a> 底下的 php 設定是正確的, 而且可以正確使用 PATH_INFO 就可以運作了.</p><ul><li>在 ngnix 上頭, 應該只要下面的設定就可以有基本的運作:</li></ul><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">location / {<br /> if (!-e $request_filename) {<br /> rewrite ^/index\.php/(.+)$ /index.php?kohana_uri=$1 last;<br /> rewrite ^/(.+)$ /index.php?kohana_uri=$1 last;<br /> rewrite ^/$ /index.php?kohana_uri=/ last;<br /> }<br /> try_files $uri $uri/ =<span class="nu0">404</span>;<br />}</pre></div></pre><p>因為 Gallery 3 是用 <a href="http://kohanaframework.org/" target="_blank">kohana</a> 這個 PHP framework 寫的, 所以 URL 實際都是轉成 kohana_uri 這個變數去處理. 第一個 rewrite 是把 PATH_INFO 轉成 kohana_uri, 第二個 rewrite 是不使用 index.php 時, 一樣把 PATH_INFO 轉成 kohana_uri, 第三個 rewrite 是主頁面的轉換.</p><ul><li>接著是相簿的封面縮圖的處理:</li></ul><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">location ~ /\.album\.jpg {<br /> <span class="kw1">allow</span> <span class="kw2">all</span>;<br /> access_log <span class="kw2">off</span>;<br /> log_not_found <span class="kw2">off</span>;<br />}</pre></div></pre><p>在 Gallery 3 是用 .album.jpg 這個檔名來當成封面, 一般來說, 在 nginx 上, 我們可能會把 .xxx 的檔案給
deny 掉, 如果有這類的處理, 在這條 rule 之前, 記得加上對 .album.jpg 的處理, 否則會看不到封面縮圖.</p><ul><li>對 <a href="http://codex.gallery2.org/Gallery_Remote" target="_blank">Gallery Remote</a> 的處理:</li></ul><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># for gallery remote</span><br />location ~ ^/main\.php$ {<br /> return 404;<br />}<br />location ~ ^/gallery_remote2\.php$ {<br /> rewrite ^/gallery_remote2\.php(.*)$ /index.php?kohana_uri=/gallery_remote$1 last;<br />}</pre></div></pre><p>只要把 /gallery_remote2.php 轉向處理就可以. 另外, 記得把 modules/gallery/config/cookie.php 裡頭的 $config['httponly'] 改成 false 才可以讓 Gallery Remote 正常連線.</p><ul><li>對於 /var 路徑下頭檔案的管理:</li></ul><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">location ~ ^/var/(albums|resizes|thumbs)/ {<br /> rewrite ^(.*)$ /index.php?kohana_uri=/file_proxy/$1 last;<br />}<br />location ~ ^/var/(logs|tmp|uploads)/ {<br /> <span class="kw1">deny</span> <span class="kw2">all</span>;<br />}</pre></div></pre><p>由於 Gallery 3 又把資料放回程式所在的目錄下, 不像 Gallery 2 是放在其他的目錄, 所以.... 只要有人知道正確的 URL, 就可以存取到 /var 下頭的檔案. 因此, 我們必須加上這些目錄的設定. 其中 logs, tmp, uploads 是完全不允許存取的. 而 albums, resizes, thumbs 在預設的情形下, 是完全沒有限制的... 而且在 Gallery 3 的正常運作下, 它只針對 Apache 來處理, 也就是當你對某個相簿做權限管理之後, 才會在該相簿的目錄下加上一個 .htaccess 的檔案來做 rewrite 到 /file_proxy/ 去檢查. 但是... nginx 完全不看 .htaccess (而且 rewrite 寫法也不同), 所以... 對於 nginx 來說, 最好是直接把這些目錄都轉給 /file_proxy/ 去處理. 就算你是用 Apache, 我也建議用同樣的設定, 因為... 有些模組會加上密碼或隱藏的功能, 如果不做這個轉向, 就會跳過這部份的權限檢查 (實際上就算轉向也會跳過檢查, 還是要改一下程式才可以).</p><ul><li>把 /index.php 由 URL 移除:</li></ul><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff -Nur gallery3.orig/application//config/config.php gallery3/application//config/config.php<br /><span class="re3">--- gallery3.orig/application//config/config.php <span class="nu0">2011</span>-05-<span class="nu0">25</span> <span class="nu0">12</span>:04:<span class="nu0">04.000000000</span> +0800</span><br /><span class="re4">+++ gallery3/application//config/config.php <span class="nu0">2011</span>-<span class="nu0">12</span>-<span class="nu0">12</span> <span class="nu0">12</span>:<span class="nu0">50</span>:<span class="nu0">29.634534543</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">54</span>,<span class="nu0">7</span> +<span class="nu0">54</span>,<span class="nu0">8</span> @@</span><br /> *<br /> * This can be removed by using URL rewriting.<br /> */<br /><span class="re7">-$config<span class="br0">[</span>"index_page"<span class="br0">]</span> = isset<span class="br0">(</span>$_GET<span class="br0">[</span>"kohana_uri"<span class="br0">]</span><span class="br0">)</span> ? "" : "index.php";</span><br /><span class="re8">+//$config<span class="br0">[</span>"index_page"<span class="br0">]</span> = isset<span class="br0">(</span>$_GET<span class="br0">[</span>"kohana_uri"<span class="br0">]</span><span class="br0">)</span> ? "" : "index.php";</span><br /><span class="re8">+$config<span class="br0">[</span>"index_page"<span class="br0">]</span> = "";</span><br /> <br /> /**<br /> * Fake file extension that will be added to all generated URLs. Example: .html</pre></div></pre><p>就是把 $config['index_page'] 設成空的就可以.</p><ul><li>把 wind 的畫面寬度變大:</li></ul><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff -Nur gallery3.orig/themes//wind/css/screen.css gallery3/themes//wind/css/screen.css<br /><span class="re3">--- gallery3.orig/themes//wind/css/screen.css <span class="nu0">2011</span>-05-<span class="nu0">25</span> <span class="nu0">12</span>:04:<span class="nu0">04.000000000</span> +0800</span><br /><span class="re4">+++ gallery3/themes//wind/css/screen.css <span class="nu0">2011</span>-<span class="nu0">12</span>-<span class="nu0">12</span> <span class="nu0">12</span>:<span class="nu0">57</span>:<span class="nu0">51.173943714</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">397</span>,<span class="nu0">10</span> +<span class="nu0">397</span>,<span class="nu0">14</span> @@</span><br /> position: relative;<br /> <span class="br0">}</span><br /> <br /><span class="re8">+#doc4 <span class="br0">{</span></span><br /><span class="re8">+ width: 99%;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /> #g-content <span class="br0">{</span><br /> padding-left: 20px;<br /> position: relative;<br /><span class="re7">- width: 696px;</span><br /><span class="re8">+ width: 98%;</span><br /> <span class="br0">}</span><br /> <br /> #g-sidebar <span class="br0">{</span></pre></div></pre><p>把寬度用百分比來算, 記得加上 #doc4 的處理才有作用.</p><ul><li>把除錯的訊息打開, 在 Gallery 3 的目錄加上 local.php, 內容如下:</li></ul><span class="sy1"></span> <pre class="php"><div class="insertcode"><pre class="php" style="font-family: monospace"><span class="sy1"><?</span> <a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">(</span><span class="st0">"SYSPATH"</span><span class="br0">)</span> or <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">(</span><span class="st0">"No direct script access"</span><span class="br0">)</span><span class="sy0">;</span><br /><a href="http://www.php.net/error_reporting"><span class="kw3">error_reporting</span></a><span class="br0">(</span><span class="kw4">E_ALL</span><span class="br0">)</span><span class="sy0">;</span><br /><a href="http://www.php.net/ini_set"><span class="kw3">ini_set</span></a><span class="br0">(</span><span class="st_h">'display_errors'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">)</span><span class="sy0">;</span></pre></div></pre><p>因為.... Galley 3 感覺並不像完成品.... 所以, 把除錯訊息打開才方便找問題發生點. </p>
Gallery
Nginx
2011-12-15T10:00:16Z
tommy
-
Gallery Remote 在使用 nginx 時無法登入的問題
https://blog.teatime.com.tw/1/post/387
<p>這幾天在測試 <a href="http://gallery.menalto.com/" target="_blank">Gallery3</a>, 測試 <a href="http://codex.gallery2.org/Gallery_Remote" target="_blank">Gallery Remote</a> 時, 發現原本裝的 Gallery2 在使用 Gallery Remote 時也無法正常登入. 登入時會出現這個錯誤訊息:</p><pre class="php"><div class="insertcode"><pre class="php" style="font-family: monospace"><a href="http://codex.gallery2.org/Gallery_Remote:FAQ#Connecting_to_a_G2_installation:_Server_contacted.2C_but_Gallery_not_found_at_this_URL" target="_blank">Server contacted<span class="sy0">,</span> but Gallery not found at this URL</a> </pre></div></pre><p>這錯誤在 Gallery Remote 的 FAQ 裡頭就有, 應該是一開始執行是會去使用 gallery_remote2.php, 如果不存在, 才會轉用別的 URL, 而在 Gallery2 的時候, 是沒有 gallery_remote2.php 的, 正常來說, 這個存取會回傳 404 not found 的錯誤, 不過... 由於我的 nginx 有對 404 做轉向的處理, 結果... 會造成實際收到的是 302 的轉向回應, 所以... 接下去就動作就不正常了. </p><p>原本希望保留我在 nginx 下的轉向設定, 只針對 gallery_remote2.php 回應 404 就可以. 不過... 試了一下, 發現似乎不能這樣子處理, 因為只要有轉向的設定, 不過是透過 php 去回應 404, 或在 nginx 對該 URL 回應 404, 都還是會去做轉向的動作.</p><p>最後... 只好在使用 Gallery2 的這個 virtual host 中不去對 404 做轉向處理, 改成回應 404 的錯誤. 如:</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace">error_page 404 /internal_error_404_page.html;<br />location /internal_error_404_page.html {<br /> internal;<br />}</pre></div></pre><p>這樣子改之後, 就可以正常登入了.</p>
Gallery
Nginx
2011-12-14T10:14:21Z
tommy
-
Nginx 的 userdir 設定
https://blog.teatime.com.tw/1/post/386
<p><a href="http://nginx.org/" target="_blank">Nginx</a> 本身沒有支援 Userdir 的模組, 不過, 可以很容易的用 location 的方式來設定.</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># user directory</span><br /><span class="co1"># ~user => /home/user/public_html</span><br /><span class="co1">#</span><br /><span class="co1"># php support</span><br />location ~ ^/~(?<USER>.+?)(?<SCRIPT_NAME>/.+\.(php|php3|phtml|suphp))(?<PATH_INFO>.*)$ {<br /> if ($PATH_INFO = <span class="st0">""</span>) {<br /> <span class="co1"># avoid empty path_info</span><br /> set $PATH_INFO $SCRIPT_NAME;<br /> }<br /> root /home/$USER/public_html;<br /> set $fpm_url unix:/var/run/php-fpm.sock;<br /> if (-f /etc/php5/fpm/pool.d/$USER.conf) {<br /> set $fpm_url unix:/var/run/php-fpm/$USER.sock;<br /> }<br /> fastcgi_index index.php;<br /> <span class="kw1">include</span> fastcgi_params;<br /> fastcgi_param PATH_INFO $PATH_INFO;<br /> fastcgi_param PATH_TRANSLATED $document_root$PATH_INFO;<br /> fastcgi_param SCRIPT_NAME $SCRIPT_NAME;<br /> fastcgi_param SCRIPT_FILENAME $document_root$SCRIPT_NAME;<br /> fastcgi_pass $fpm_url;<br />}<br /><span class="co1"># static files</span><br />location ~ ^/~(?<USER>.+?)(?<SCRIPT_NAME>(/.*)|)$ {<br /> <span class="kw1">alias</span> /home/$USER/public_html$SCRIPT_NAME;<br /> index index.php index.html index.htm;<br /> <span class="co1"># enable autoindex for users</span><br /> autoindex <span class="kw2">on</span>;<br />}</pre></div></pre><p>記得 <a href="http://www.php.net/" target="_blank">php</a> 的部份, 同樣要另外處理, 而且因為網址會有轉換, 並沒有直接套用原本系統的 php 設定. </p>
Nginx
2011-12-03T12:08:06Z
tommy
-
Lifetype 在 nginx 的 rewrite 處理
https://blog.teatime.com.tw/1/post/385
<p><a href="http://lifetype.net/" target="_blank">Lifetype</a> 同樣只提供 <a href="http://www.apache.org/" target="_blank">Apache</a> 的 rewrite 處理, 所以... 我們一樣需要轉換為 <a href="http://nginx.org/" target="_blank">nginx</a> 的方式.</p><p>底下是我用的方式 (我是用自訂的格式, 並不是 Lifetype 預設的那種簡短網址, 所以... 如果你要用, 還是要改一下才有作用):</p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># Lifetype rewrtie rule</span><br /><span class="co1">#</span><br /><span class="co1"># sitemap</span><br /><span class="co1"># /sitemap1.tgz</span><br />rewrite ^/sitemap([0-9]+)\.gz$ /tmp/sitemap/$1/sitemap.gz last;<br /> <br /><span class="co1"># post</span><br /><span class="co1"># /1/post/3</span><br />rewrite ^/([0-9]+)/post/([0-9]+)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2 last;<br />rewrite ^/([0-9]+)/post/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2&page=$3 last;<br /><span class="co1"># /1/aechive/3</span><br />rewrite ^/([0-9]+)/archive/([0-9]+)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2 last;<br />rewrite ^/([0-9]+)/archive/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2&page=$3 last;<br /><span class="co1"># /post/1/3</span><br />rewrite ^/post/([0-9]+)/([0-9]+)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2 last;<br />rewrite ^/post/([0-9]+)/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2&page=$3 last;<br /><span class="co1"># /aechive/1/3</span><br />rewrite ^/archive/([0-9]+)/([0-9]+)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2 last;<br />rewrite ^/archive/([0-9]+)/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewArticle&blogId=$1&articleId=$2&page=$3 last;<br /> <br /><span class="co1"># Monthly/Daily archive</span><br /><span class="co1"># /1/archives/200401</span><br />rewrite <span class="st0">"^/([0-9]+)/archives/([0-9]{6})$"</span> /index.php?op=Default&blogId=$1&Date=$2 last;<br />rewrite <span class="st0">"^/([0-9]+)/archives/([0-9]{6})/page/([1-9][0-9]*)$"</span> /index.php?op=Default&blogId=$1&Date=$2&page=$3 last;<br /><span class="co1"># /1/archives/20040101</span><br />rewrite <span class="st0">"^/([0-9]+)/archives/([0-9]{8})$"</span> /index.php?op=Default&blogId=$1&Date=$2 last;<br />rewrite <span class="st0">"^/([0-9]+)/archives/([0-9]{8})/page/([1-9][0-9]*)$"</span> /index.php?op=Default&blogId=$1&Date=$2&page=$3 last;<br /><span class="co1"># /archives/1/200401</span><br />rewrite <span class="st0">"^/archives/([0-9]+)/([0-9]{6})$"</span> /index.php?op=Default&blogId=$1&Date=$2 last;<br />rewrite <span class="st0">"^/archives/([0-9]+)/([0-9]{6})/page/([1-9][0-9]*)$"</span> /index.php?op=Default&blogId=$1&Date=$2&page=$3 last;<br /><span class="co1"># /archives/1/20040101</span><br />rewrite <span class="st0">"^/archives/([0-9]+)/([0-9]{8})$"</span> /index.php?op=Default&blogId=$1&Date=$2 last;<br />rewrite <span class="st0">"^/archives/([0-9]+)/([0-9]{8})/page/([1-9][0-9]*)$"</span> /index.php?op=Default&blogId=$1&Date=$2&page=$3 last;<br /> <br /><span class="co1"># Album</span><br /><span class="co1"># /88/album/34</span><br />rewrite ^/([0-9]+)/album/([0-9]+)$ /index.php?op=ViewAlbum&blogId=$1&albumId=$2 last;<br />rewrite ^/([0-9]+)/album/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewAlbum&blogId=$1&albumId=$2&page=$3 last;<br /><span class="co1"># /album/88/34</span><br />rewrite ^/album/([0-9]+)/([0-9]+)$ /index.php?op=ViewAlbum&blogId=$1&albumId=$2 last;<br />rewrite ^/album/([0-9]+)/([0-9]+)/page/([1-9][0-9]*)$ /index.php?op=ViewAlbum&blogId=$1&albumId=$2&page=$3 last;<br /> <br /><span class="co1"># Albums</span><br /><span class="co1"># /88/album/</span><br />rewrite ^/([0-9]+)/album/$ /index.php?op=ViewAlbum&blogId=$1&albumId=0 last;<br /><span class="co1"># /album/88/</span><br />rewrite ^/album/([0-9]+)/$ /index.php?op=ViewAlbum&blogId=$1&albumId=0 last;<br /> <br /><span class="co1"># Category view</span><br /><span class="co1"># /88/categories/4</span><br />rewrite ^/([0-9]+)/categories/([0-9]+)$ /index.php?blogId=$1&postCategoryId=$2 last;<br />rewrite ^/([0-9]+)/categories/([0-9]+)/page/([1-9][0-9]*)$ /index.php?blogId=$1&postCategoryId=$2&page=$3 last;<br /><span class="co1"># /88/category/4</span><br />rewrite ^/([0-9]+)/category/([0-9]+)$ /index.php?blogId=$1&postCategoryId=$2 last;<br />rewrite ^/([0-9]+)/category/([0-9]+)/page/([1-9][0-9]*)$ /index.php?blogId=$1&postCategoryId=$2&page=$3 last;<br /><span class="co1"># /categories/88/4</span><br />rewrite ^/categories/([0-9]+)/([0-9]+)$ /index.php?blogId=$1&postCategoryId=$2 last;<br />rewrite ^/categories/([0-9]+)/([0-9]+)/page/([1-9][0-9]*)$ /index.php?blogId=$1&postCategoryId=$2&page=$3 last;<br /><span class="co1"># /category/88/4</span><br />rewrite ^/category/([0-9]+)/([0-9]+)$ /index.php?blogId=$1&postCategoryId=$2 last;<br />rewrite ^/category/([0-9]+)/([0-9]+)/page/([1-9][0-9]*)$ /index.php?blogId=$1&postCategoryId=$2&page=$3 last;<br /> <br /><span class="co1"># Category-Feeds</span><br /><span class="co1"># /3/feeds/categories/2/atom</span><br />rewrite ^/([0-9]+)/feeds/categories/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /><span class="co1"># /feeds/3/categories/2/atom</span><br />rewrite ^/feeds/([0-9]+)/categories/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /><span class="co1"># /feeds/categories/3/2/atom</span><br />rewrite ^/feeds/categories/([0-9]+)/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /><span class="co1"># /3/rss/categories/2/atom</span><br />rewrite ^/([0-9]+)/rss/categories/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /><span class="co1"># /rss/3/categories/2/atom</span><br />rewrite ^/rss/([0-9]+)/categories/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /><span class="co1"># /rss/categories/3/2/atom</span><br />rewrite ^/rss/categories/([0-9]+)/([0-9]+)/(.+)$ /rss.php?blogId=$1&categoryId=$2&profile=$3 last;<br /> <br /><span class="co1"># Feeds</span><br /><span class="co1"># /3/feeds/atom</span><br />rewrite ^/([0-9]+)/feeds/(.+)$ /rss.php?blogId=$1&profile=$2 last;<br /><span class="co1"># /feeds/3/atom</span><br />rewrite ^/feeds/([0-9]+)/(.+)$ /rss.php?blogId=$1&profile=$2 last;<br /><span class="co1"># /feeds/atom/3</span><br />rewrite ^/feeds/(.+)/([0-9]+)$ /rss.php?blogId=$2&profile=$1 last;<br /><span class="co1"># /3/rss/atom</span><br />rewrite ^/([0-9]+)/rss/(.+)$ /rss.php?blogId=$1&profile=$2 last;<br /><span class="co1"># /rss/3/atom</span><br />rewrite ^/rss/([0-9]+)/(.+)$ /rss.php?blogId=$1&profile=$2 last;<br /><span class="co1"># /rss/atom/3</span><br />rewrite ^/rss/(.+)/([0-9]+)$ /rss.php?blogId=$2&profile=$1 last;<br /> <br /><span class="co1"># Trackbacks</span><br /><span class="co1"># /3/trackbacks/34</span><br />rewrite ^/([0-9]+)/trackbacks/([0-9]+)$ /index.php?op=Trackbacks&blogId=$1&articleId=$2 last;<br /><span class="co1"># /trackbacks/3/34</span><br />rewrite ^/trackbacks/([0-9]+)/([0-9]+)$ /index.php?op=Trackbacks&blogId=$1&articleId=$2 last;<br /> <br /><span class="co1"># Comment form</span><br /><span class="co1"># /88/comment/34</span><br />rewrite ^/([0-9]+)/comment/([0-9]+)$ /index.php?op=Comment&blogId=$1&articleId=$2 last;<br /><span class="co1"># /comment/88/34</span><br />rewrite ^/comment/([0-9]+)/([0-9]+)$ /index.php?op=Comment&blogId=$1&articleId=$2 last;<br /> <br /><span class="co1"># Resources</span><br /><span class="co1"># /88/resource/1/2</span><br />rewrite ^/([0-9]+)/resource/([0-9]+)/([0-9]+)$ /index.php?op=ViewResource&blogId=$1&albumId=$2&resId=$3 last;<br /><span class="co1"># /resource/88/1/2</span><br />rewrite ^/resource/([0-9]+)/([0-9]+)/([0-9]+)$ /index.php?op=ViewResource&blogId=$1&albumId=$2&resId=$3 last;<br /><span class="co1"># Download a resource</span><br /><span class="co1"># /88/gallery/this-is-a-resource-name.pdf</span><br /><span class="co1">#rewrite ^/([0-9]+)/gallery/(.+)$ /resserver.php?blogId=$1&resource=$2 last;</span><br /><span class="co1"># /get/88/this-is-a-resource-name.pdf</span><br /><span class="co1">#rewrite ^/gallery/([0-9]+)/(.+)$ /resserver.php?blogId=$1&resource=$2 last;</span><br /> <br /><span class="co1"># A non-default blog</span><br /><span class="co1"># /88</span><br />rewrite ^/([0-9]+)$ /index.php?blogId=$1 last;<br />rewrite ^/([0-9]+)/index\.php$ /index.php?blogId=$1 last;<br />rewrite ^/([0-9]+)/page/([1-9][0-9]*)$ /index.php?blogId=$1&page=$2 last;<br /> <br /><span class="co1"># default blog</span><br /><span class="co1"># /</span><br />rewrite ^/$ /index.php?blogId=1 last;<br /> <br /><span class="co1"># Static Pages</span><br /><span class="co1"># /3/demosites</span><br />#<strike>rewrite ^/([0-9]+)/(.+)$ /index.php?op=Template&blogId=$1&show=$2 last;</strike></pre></div></pre><p>除了上面這些外, 因為有裝 <a href="http://gallery.menalto.com/" target="_blank">Gallery</a> 的 plugins, 所以也要處理 Gallery 的部份: </p><pre class="apache"><div class="insertcode"><pre class="apache" style="font-family: monospace"><span class="co1"># Galley begin</span><br /><span class="co1"># Gallery</span><br /><span class="co1"># for index.php?op=gallery</span><br />rewrite ^/([0-9]+)/index(.+)$ /index$2 last;<br /> <br /><span class="co1">#</span><br /><span class="co1"># from gallery's .htaccess</span><br /><span class="co1"># 1. insert /([0-9]+)/ to /xxx</span><br /><span class="co1"># 2. change !/main\.php$ to !index\.php$</span><br /><span class="co1"># 3. change /main.php? to index.php?op=gallery&</span><br /><span class="co1"># 4. shift parameter, add 1 to them</span><br />rewrite ^/([0-9]+)/sitemap$ /index.php?op=gallery&g2_view=sitemap.Sitemap last;<br />rewrite ^/([0-9]+)/updates$ /index.php?op=gallery&g2_view=dynamicalbum.UpdatesAlbum last;<br />rewrite ^/([0-9]+)/popular$ /index.php?op=gallery&g2_view=dynamicalbum.PopularAlbum last;<br />rewrite ^/([0-9]+)/admin/$ /index.php?op=gallery&g2_view=core.SiteAdmin last;<br />rewrite ^/([0-9]+)/radom([^\?]+)$ /index.php?op=gallery&g2_view=dynamicalbum.RandomAlbum last;<br />rewrite ^/([0-9]+)/v/([^\?]+)/slideshowapplet\.html$ /index.php?op=gallery&g2_view=slideshowapplet.SlideshowApplet&g2_path=$2 last;<br />rewrite ^/([0-9]+)/d/([0-9]+)-([0-9]+)/([^\?]+)$ /index.php?op=gallery&g2_view=core.DownloadItem&g2_itemId=$2&g2_serialNumber=$3&g2_fileName=$4 last;<br />rewrite ^/([0-9]+)/v/([^\?]+)/slideshow\.html$ /index.php?op=gallery&g2_view=slideshowapplet.Slideshow&g2_path=$2 last;<br />rewrite ^/([0-9]+)/rating/([^?/]+)$ /index.php?op=gallery&g2_view=rating.RatingAlbum&g2_limit=$2 last;<br />rewrite ^/([0-9]+)/rss/([^\/\?]+)$ /index.php?op=gallery&g2_view=rss.Render&g2_name=$2 last;<br />rewrite ^/([0-9]+)/srss/([0-9]+)$ /index.php?op=gallery&g2_view=rss.SimpleRender&g2_name=$2 last;<br />rewrite ^/([0-9]+)/key/([^?/]+)$ /index.php?op=gallery&g2_view=keyalbum.KeywordAlbum&g2_keyword=$2 last;<br />rewrite ^/([0-9]+)/f/([^\?]+)$ /index.php?op=gallery&g2_controller=permalinks.Redirect&g2_filename=$2 last;<br />rewrite ^/([0-9]+)/v/([^\?]+)$ /index.php?op=gallery&g2_path=$2 last;<br /><strike>#rewrite ^/([0-9]+)/([^\?]+)$ /index.php?op=gallery&g2_view=rewrite.FileNotFound last;</strike><br /><span class="co1">#rewrite ^/([0-9]+)/([^\?]+)$ /index.php?op=gallery&g2_controller=migrate.Redirect&g2_path=$2;</span></pre></div></pre><p>最後, 與 nginx 沒什麼關係, 不過與 <a href="http://www.php.net/" target="_blank">php</a> 有點關係. 新版本的 php 有可能會有個 intl 的模組, 如果包含這個 php5-intl 的話, 裡頭會有 Locale 這個 Class 存在. 因為 LifeType 也有一個同樣名稱的 class, 所以... 就會無法執行了. 解決方法就是不要用 php5-intl 或把 LifeType 更新到 1.1.12 (還沒推出, 所以只能抓 <a href="http://lifetype.net/snapshots/" target="_blank">snapshot</a> 或 svn 裡頭的版本). </p><hr width="100%" size="2" /><br />2011/12/10:<br />修正一下 static page 的 rewrite, 這會影響後頭 gallery 的 rewrite, 如果要用, 記得把這個放到最後頭. (gallery 的 rewrite 也有一個類似的設定, 同樣記得取消)
LifeType
Nginx
2011-12-03T11:56:08Z
tommy
-
Gallery2 在 nginx 底下的 rewrite 處理
https://blog.teatime.com.tw/1/post/384
<p>由於 <a href="http://gallery.menalto.com/" target="_blank">Gallery2</a> 只有提供 <a href="http://www.apache.org/" target="_blank">Apache</a> 的 rewrite 設定, 所以當轉換到 <a href="http://nginx.org/" target="_blank">nginx</a> 使用的時候, 就要想辦法自己來改寫.</p><p>我自己對於 gallery 的 virtualhost 設定像這樣:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">server <span class="br0">{</span><br /> root /usr/share/gallery2<span class="co0">;</span><br /> index index.php<span class="co0">;</span><br /> <br /> server_name gallery.teatime.com.tw *.gallery.teatime.com.tw<span class="co0">;</span><br /> <br /> access_log /var/log/nginx/gallery-access.log<span class="co0">;</span><br /> error_log /var/log/nginx/gallery-error.log<span class="co0">;</span><br /> <br /> # rewrite rule for gallery<br /> include conf/gallery2_rewrite.conf<span class="co0">;</span><br /> <br /> location / <span class="br0">{</span><br /> set $flag true<span class="co0">;</span><br /> set $get_image false<span class="co0">;</span><br /> valid_referers none blocked *.teatime.com.tw<span class="co0">;</span><br /> if <span class="br0">(</span>$invalid_referer<span class="br0">)</span> <span class="br0">{</span><br /> set $flag false<span class="co0">;</span><br /> <span class="br0">}</span><br /> if <span class="br0">(</span>$query_string ~ core\.DownloadItem<span class="br0">)</span> <span class="br0">{</span><br /> set $get_image true<span class="co0">;</span><br /> <span class="br0">}</span><br /> if <span class="br0">(</span>$get_image <span class="sy0">=</span><span class="re2"> false<span class="br0">)</span> <span class="br0">{</span></span><br /> set $flag true<span class="co0">;</span><br /> <span class="br0">}</span><br /> if <span class="br0">(</span>$flag <span class="sy0">=</span><span class="re2"> false<span class="br0">)</span> <span class="br0">{</span></span><br /> return <span class="nu0">403</span><span class="co0">;</span><br /> <span class="br0">}</span><br /> if <span class="br0">(</span>$bots<span class="br0">)</span> <span class="br0">{</span><br /> return <span class="nu0">403</span><span class="co0">;</span><br /> <span class="br0">}</span><br /> try_files $uri $uri/ index.php?q<span class="sy0">=</span><span class="re2">$uri index.html?q=uri =404</span><span class="co0">;</span><br /> <span class="br0">}</span><br /> <br /> # rule from .htaccess<br /> location ~* ^/lib/tool/po/ <span class="br0">{</span><br /> deny all<span class="co0">;</span><br /> <span class="br0">}</span><br /> location ~* \.<span class="br0">(</span>class|inc|xml<span class="br0">)</span> <span class="br0">{</span><br /> deny all<span class="co0">;</span><br /> <span class="br0">}</span><br /> # if we need to upgrade, remove this<br /> location ~* ^/.+/.+\.php <span class="br0">{</span><br /> deny all<span class="co0">;</span><br /> <span class="br0">}</span><br /> location ~* ^/config\.php <span class="br0">{</span><br /> deny all<span class="co0">;</span><br /> <span class="br0">}</span><br /> location ~* ^\.inc <span class="br0">{</span><br /> deny all<span class="co0">;</span><br /> <span class="br0">}</span><br /> <br /> # redirect server error <span class="nu0">404</span><br /> include conf/error_404.conf<span class="co0">;</span><br /> # redirect server error pages to the static page /50x.html<br /> include conf/error_50x.conf<span class="co0">;</span><br /> # deny some access<br /> include conf/drop.conf<span class="co0">;</span><br /> <br /> # php support, reject $bots<br /> include conf/php_no_bots.conf<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>上頭有些對於原本 .htaccess 阻擋設定的轉換, 另外 rewrite rule 由於比較多, 就寫成另一個 conf/gallery2_rewrite.conf 的設定檔如下:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace"># gallery2<br />if <span class="br0">(</span>!-e $request_filename<span class="br0">)</span> <span class="br0">{</span><br /> rewrite ^/sitemap$ /main.php?g2_view<span class="sy0">=</span><span class="re2">sitemap.Sitemap last</span><span class="co0">;</span><br /> rewrite ^/updates$ /main.php?g2_view<span class="sy0">=</span><span class="re2">dynamicalbum.UpdatesAlbum last</span><span class="co0">;</span><br /> rewrite ^/popular$ /main.php?g2_view<span class="sy0">=</span><span class="re2">dynamicalbum.PopularAlbum last</span><span class="co0">;</span><br /> rewrite ^/admin/$ /main.php?g2_view<span class="sy0">=</span><span class="re2">core.SiteAdmin last</span><span class="co0">;</span><br /> rewrite ^/radom<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">dynamicalbum.RandomAlbum last</span><span class="co0">;</span><br /> rewrite ^/v/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>/slideshowapplet\.html$ /main.php?g2_view<span class="sy0">=</span><span class="re2">slideshowapplet.SlideshowApplet&g2_path=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/d/<span class="br0">(</span><span class="re0"><span class="br0">[</span><span class="nu0">0</span>-<span class="nu0">9</span><span class="br0">]</span>+<span class="br0">)</span>-<span class="br0">(</span><span class="br0">[</span><span class="nu0">0</span>-<span class="nu0">9</span><span class="br0">]</span>+<span class="br0">)</span>/<span class="br0">(</span><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">core.DownloadItem&g2_itemId=$<span class="nu0">1</span>&g2_serialNumber<span class="sy0">=</span>$<span class="nu0">2</span>&g2_fileName<span class="sy0">=</span>$<span class="nu0">3</span> last</span><span class="co0">;</span><br /> rewrite ^/v/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>/slideshow\.html$ /main.php?g2_view<span class="sy0">=</span><span class="re2">slideshowapplet.Slideshow&g2_path=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/rating/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^?/<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">rating.RatingAlbum&g2_limit=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/rss/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\/\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">rss.Render&g2_name=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/srss/<span class="br0">(</span><span class="re0"><span class="br0">[</span><span class="nu0">0</span>-<span class="nu0">9</span><span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">rss.SimpleRender&g2_name=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/key/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^?/<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">keyalbum.KeywordAlbum&g2_keyword=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/f/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_controller<span class="sy0">=</span><span class="re2">permalinks.Redirect&g2_filename=$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/v/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_path<span class="sy0">=</span><span class="re2">$<span class="nu0">1</span> last</span><span class="co0">;</span><br /> rewrite ^/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_view<span class="sy0">=</span><span class="re2">rewrite.FileNotFound last</span><span class="co0">;</span><br /> #rewrite ^/<span class="br0">(</span><span class="re0"><span class="br0">[</span>^\?<span class="br0">]</span></span>+<span class="br0">)</span>$ /main.php?g2_controller<span class="sy0">=</span><span class="re2">migrate.Redirect&g2_path=$1</span><span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>原本以為這樣子處理就可以了. (因為初步的測試都正常)</p><p>不過, 幾天後, 有人反應某些照片看不到縮圖, 也點不進去看該照片.... 比對之後, 發現檔名有空白字元的都不行 (由於目錄在建立時 Gallery 不允許空白, 所以目錄不會有問題). 原本檔案名稱如果有空白, 所轉出來的網址會用 + 來取代空白.</p><p>但是 nginx 在 rewrite 時, 會把 + 轉成 %2b, 所以... Gallery 收到後, 只會做一次轉換, 也就是把 %2b 轉回 +, 然後就去找那個檔案... 因為 + 應該是空白才對, 自然會找不到該檔案.</p><p>原本想由 nginx 這兒來修正, 不過... 想了又想, 實在找不出有什麼方法可以把這個轉換在 nginx 給改回來 (有人知道嗎?), 所以... 就只好去改 Gallery2 的程式碼了. </p><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">--- modules/core/classes/GalleryUtilities.class 2011-11-26 13:58:40.186252459 +0800<br /><span class="re4">+++ modules.patch/core/classes/GalleryUtilities.class <span class="nu0">2011</span>-<span class="nu0">11</span>-<span class="nu0">30</span> <span class="nu0">15</span>:<span class="nu0">28</span>:<span class="nu0">51.790757672</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">237</span>,<span class="nu0">9</span> +<span class="nu0">237</span>,<span class="nu0">27</span> @@</span><br /> */<br /> function getRequestVariables<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><br /> $values = array<span class="br0">(</span><span class="br0">)</span>;<br /><span class="re8">+ // twu2 begin</span><br /><span class="re8">+ // is running in nginx?</span><br /><span class="re8">+ $is_nginx = strncmp<span class="br0">(</span>$_SERVER<span class="br0">[</span>'SERVER_SOFTWARE'<span class="br0">]</span>, 'nginx', 5<span class="br0">)</span> == 0 ? true : false;</span><br /><span class="re8">+ // twu2 end</span><br /> foreach <span class="br0">(</span>func_get_args<span class="br0">(</span><span class="br0">)</span> as $argName<span class="br0">)</span> <span class="br0">{</span><br /><span class="re8">+/* original code</span><br /> $values<span class="br0">[</span><span class="br0">]</span> = GalleryUtilities::_getRequestVariable<span class="br0">(</span><br /> GALLERY_FORM_VARIABLE_PREFIX . $argName<span class="br0">)</span>;<br /><span class="re8">+*/</span><br /><span class="re8">+ $s = GalleryUtilities::_getRequestVariable<span class="br0">(</span></span><br /><span class="re8">+ GALLERY_FORM_VARIABLE_PREFIX . $argName<span class="br0">)</span>;</span><br /><span class="re8">+ // twu2 begin</span><br /><span class="re8">+ // maybe fix the issue with nginx, it change + to %2b</span><br /><span class="re8">+ // then we got + here <span class="br0">(</span>in fact , it's ' '<span class="br0">)</span></span><br /><span class="re8">+ // only convert for g2_path and g2_fileName</span><br /><span class="re8">+ if <span class="br0">(</span>$is_nginx && <span class="br0">(</span>$argName == 'path' || $argName == 'fileName'<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ $x = str_replace<span class="br0">(</span>'+', ' ', $s<span class="br0">)</span>;</span><br /><span class="re8">+ $s = $x;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ $values<span class="br0">[</span><span class="br0">]</span> = $s;</span><br /><span class="re8">+ // twu2 end</span><br /> <span class="br0">}</span><br /> <br /> /* Sanitize the input */</pre></div></pre><p>在 Gallery 中, 如果發現是在 nginx 底下執行時, 就去把 g2_path 與 g2_fileName 這兩個參數的 + 改成空白 (因為 Gallery 在接受照片的檔名時, 會把 + 改成 _ 來命名, 所以實際上不會存在含有 + 字元的檔名, 這樣子改應該不會有問題).</p><p>經過這樣的修改後, 看起來目前都還正常. (會不會有其他的問題.... 就碰到了才會知道了) </p>
Gallery
PHP
Nginx
2011-12-02T16:51:14Z
tommy
-
Nginx/FastCGI/PHP-FPM 相關設定
https://blog.teatime.com.tw/1/post/383
<p>上個月中開始, 逐步將家裡機器裡頭的 <a href="http://www.apache.org/" target="_blank">Apache</a>/mod_php 改成 <a href="http://nginx.org/" target="_blank">Nginx</a>/FastCGI/<a href="http://php-fpm.org/" target="_blank">PHP-FPM</a> 來運作. 經過了近兩個星期的嚐試, 目前看起來應該是可以完整的取代了.</p><p>以下是在 <a href="http://www.debian.org/" target="_blank">Debian</a> Stable (Squeeze) 的安裝與設定. </p><ul><li>PHP-FPM</li></ul><p>在 <a href="http://www.php.net/" target="_blank">PHP</a> 5.3.3 之後, 這功能已經被 PHP 官方納入, 所以應該不用再自行 patch 並編譯. 不過... 雖然 Debian Squeeze 的 PHP 已經是 5.3.3 的版本, 但是並沒有把 php-fpm 給編入, 所以.... 我們還是要自己處理. 可以把 testing 裡的 php 5.3.8 source 抓回來自行編譯就可以用了.</p><p>安裝 php5-fpm 之後, 設定檔在 /etc/php5/fpm/ 底下, 基本上只要修改 /etc/php5/fpm/pool.d/www.conf 就可以了. 我是把 listen 由 tcp 改成 socket file 來使用. 另外, 可以指定不同的使用者來執行 php, 所以, 我把 www.conf 複製成 tommy.conf, 然後把 裡頭的 www 換成 tommy, 也把 user 設成 $pool (也就是 tommy), 把 listen 指定成 /var/run/php-fpm/$pool.sock (要自己建立該目錄). 這樣子重新執行後, 就會多幾個用 tommy 這個使用者執行的程式出現. 這樣子我們可以在後面的 nginx 中, 讓使用者使用自己的 user 來跑 php (就像 suphp 的作法一樣), 而不是強迫所有的人都用 httpd 的使用者來跑 php. (差別在於對於使用者本身的目錄有讀寫的權限, 如果用 httpd 的使用者來跑的話, 寫入檔案或上傳檔案之後的使用者會是 httpd 的使用者, 會有權限的問題)</p><p>另外, 如果有需要修改 php.ini 的話, 記得是去改 /etc/php5/fpm/php.ini 才可以. (後頭會提到有個地方要改) </p><ul><li>Nginx</li></ul><p>在 Debian Squeeze 的 Nginx 好像是 0.7.x 版的, 要直接用也可以. 如果要新版的, 可以用 Nginx 本身提供的版本 (stable 版本, 目前是 1.0.10), <a href="http://nginx.org/en/download.html" target="_blank">Nginx 官方下載網站</a>的底下有安裝的說明. 另外, 在 <a href="http://backports-master.debian.org/" target="_blank">Debian 的 backports 網站</a>, 也有提供新版的 Nginx (用的是 development 的版本, 1.1.0, PS. Nginx 最新的 development 版本是 1.1.10).<br /><br />把 nginx 裝起來後, 應該只要去修改 /etc/nginx/nginx.conf 裡頭有關 php 的那一段後, 執行 /etc/init.d/nginx reload 就應該可以執行 php 了. (對於沒有 rewrite 處理過, 能正確找到應該有的檔案的情形下, 應該都可以用)</p><p>聽起來很簡單吧.... 不過有些小地方我們要注意一下.</p><p>預設的設定方式可能像這樣:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php$ <span class="br0">{</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>就直接把有 .php 的 request 轉給 fastcgi 的 server (一般來說, 如果沒有非本機連線的需求時, 用 socket file 的方式應該會比較好).</p><p>不過這個方式並不能正確處理 PATH_INFO, 所以如果你的 php 程式有用到 PATH_INFO 時, 就會有問題.</p><p>而 PATH_INFO 的處理, 可以有兩種方式來處理, 一種是交給 php 本身來處理, 只要在 php.ini 把 cgi.fix_pathinfo 設成 1, 然後 nginx 中的設定改成這樣:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_param PATH_INFO $fastcgi_script_name<span class="co0">; </span><br /><span class="br0">}</span></pre></div></pre><p>把 location .php 後頭的 $ 移除, 然後加上如上頭的 PHP_INFO 參數. 這樣子 php 本身會產生正確的 PATH_INFO 與 PATH_TRANSLATED 變數. 不過... 當沒有 PATH_INFO 時, 上頭這個設定會有點不太正確, 有些程式可能反而不能正常運作 (如 Cacti), 所以, 我們可以把兩種設定都放上去, 像是:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php$ <span class="br0">{</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /><span class="br0">}</span><br />location ~ \.php <span class="br0">{</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_param PATH_INFO $fastcgi_script_name<span class="co0">; </span><br /><span class="br0">}</span></pre></div></pre><p>先設定 .php$, 再設定 .php 這樣就應該可以了. </p><p>不過目前 php 本身的處理會有安全上的問題 (google 找一下應該可以看到一些例子), 所以... 不建議由 php 來處理 PATH_INFO, 而改用 nginx 來處理. </p><p>如果要使用 nginx 來處理的話, 請將 php.ini 的 cgi.fix_pathinfo 設為 0, 再把 cgi.discard_path 設成 1 (這參數多數系統的 php.ini 裡頭都沒有, 自己加上去吧, 這是 5.3.3 之後才有的參數, 如果不設為 1, 在我的測試環境中, 有 PATH_INFO 的情況都會出現 404 的錯誤). 然後使用這樣子的設定方式:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> include fastcgi_params;<br /> fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;<br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<br /> fastcgi_param PATH_INFO $fastcgi_path_info;<br /> fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;<br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>不過, 這樣子處理, 在沒有 PATH_INFO 時, 會被 PATH_INFO 設成空字串 (但仍有這變數), 這時... PHP_SELF 也會被設成空的, 對某些使用到 PHP_SELF 的程式可能會有問題 (如 Cacti). 比較合理的方式應該是去檢查 $fastcgi_path_info 是不是空的, 如果不是才去設定 PATH_INFO 與 PATH_TRANSLATED 的值. 不過... 很可惜, nginx 並不能在 if 裡頭去設定 fastcgi_param, 所以... 沒辦法這樣子來設定. 所以... 跟上頭一樣, 我們也可以加上另一個不用 PATH_INFO 的設定, 如:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php$ <span class="br0">{</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /><span class="br0">}</span><br />location ~ \.php <span class="br0">{</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $fastcgi_path_info<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>這樣子應該不管有沒有 PATH_INFO 都可以正常使用. 不過... 就是要寫兩段... 所以, 我用另一種方式如:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>把空的 PATH_INFO 設成 $fastcgi_script_name, 這樣子在我的系統上看起來運作也是正常的. (不知道有沒有錯, 也許寫成兩段才是比較合理的方式)</p><p>接著... 前面有提到我們可以讓不同的使用者, 以他們的身份來執行 php, 所以... 例如:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm/tommy.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>如果是 tommy 這個使用者, 就去使用 tommy 的那一個 socket file.</p><p>不過... 如果有很多使用者, 就表示每一個的設定都有單獨去設... 這樣如果要改, 可能會很麻煩, 所以... 我們可以把加上一個變數來使用, 把上頭的設定獨立成一個叫 php.conf (放 /etc/nginx/conf/ 目錄下) 的檔案, 這樣在每一個使用者的設定, 只要先去指定變數再去 include conf/php.conf 就可以.</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> fastcgi_pass unix:/var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>先用 uninitialized_variable_warn off 把使用到沒初始化的變數警告關閉, 然後把 fastcgi_pass 的值加上變數來處理.</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">server <span class="br0">{</span><br /> # for user tommy<br /> set $cur_php_user tommy<span class="co0">;</span><br /> include conf/php.conf<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>這樣子在該使用者的主機設定用這方式來處理就可以了.</p><p>不過... 這時有個問題, 如果並沒有在 php-fpm 裡頭去跑那個使用者的 php 程式時, 或忘了設定 $cur_php_user 時... 就沒有那個 socket file, 這時... 執行就會有問題.</p><p>比較合理的方式應該像是:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /var/run/php-fpm/$cur_php_user.sock<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url /var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>檢查該 socket file 是否存在, 若不存在則用系統原本的那一個.</p><p>這樣看起來很完美吧. 不過... 上頭的方式是無法運作的, 因為 -f 會用 S_ISREG() 來檢查檔案是否存在, 而 socket file 用這方式查會不存在, 等於是永遠不會用該使用者的身分來執行 php. </p><p>所以... 要不就是修改 nginx 的原始碼, 加上 S_ISSOCK() 的處理, 或... 退一步, 我們檢查 php-fpm 的設定檔, 如:</p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.php <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.php<span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /etc/php5/fpm/pool.d/$cur_php_user.conf<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url /var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $cur_php_user "";<br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>這樣子, 除非加了 php-fpm 的設定檔, 但忘了重跑 php-fpm, 否則應該不會有出現找不到 fastcgi backend 的情形. </p><p>不過, 以往使用 apache 的時候, 可以讓不同的附檔名如 .php, .php3, .phtml, .suphp 都當成是 php 來執行. 這時, 在 nginx 上頭, 要怎麼處理呢?</p><p>由於 nginx 的設定都是用正規表示式來處理, 所以, 原本很簡單的想法, 就是直接把各種檔名都加上, 如: </p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ \.<span class="br0">(</span>php|php3|phtml|suphp<span class="br0">)</span> <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_split_path_info ^<span class="br0">(</span><span class="br0">(</span>?U<span class="br0">)</span>.+\.<span class="br0">(</span>php|php3|phtml|suphp<span class="br0">)</span><span class="br0">)</span><span class="br0">(</span>/?.+<span class="br0">)</span>$<span class="co0">;</span><br /> set $p $fastcgi_path_info<span class="co0">;</span><br /> if <span class="br0">(</span>$p <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> set $p $fastcgi_script_name<span class="co0">;</span><br /> <span class="br0">}</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span class="co0">;</span><br /> fastcgi_param PATH_INFO $p<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$p<span class="co0">;</span><br /> #fastcgi_pass 127.0.0.1:<span class="nu0">9000</span><span class="co0">;</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /etc/php5/fpm/pool.d/$cur_php_user.conf<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url /var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $cur_php_user <span class="st0">""</span><span class="co0">;</span><br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>看起來似乎沒錯, 不過... 由於用到了 fastcgi_split_path_info, 而這個後頭只接受傳回兩個值的正規表示式, 所以上頭的方式, 就不被 nginx 所接受. 這時... 我們只能選擇把每一種附檔名寫一段設定來處理 (這樣實在不是個好方法), 或者.. 不要用 fastcgi_split_path_info 來處理, 自行用正規表示式來處理, 如: </p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ ^<span class="br0">(</span>?<SCRIPT>/.*\.<span class="br0">(</span>php|php3|phtml|suphp<span class="br0">)</span><span class="br0">)</span><span class="br0">(</span>?<PATH_INFO>.*<span class="br0">)</span>$ <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> if <span class="br0">(</span>$PATH_INFO <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> # avoid empty path_info<br /> set $PATH_INFO $SCRIPT<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /etc/php5/fpm/pool.d/$cur_php_user.conf<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url unix:/var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $cur_php_user <span class="st0">""</span><span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_param PATH_INFO $PATH_INFO<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$PATH_INFO<span class="co0">;</span><br /> fastcgi_param SCRIPT_NAME $SCRIPT<span class="co0">;</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$SCRIPT<span class="co0">;</span><br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p>這樣子, 就能對多種附檔名都放在同一個設定裡頭了.</p><p> </p><hr width="100%" size="2" />2011/12/10:<br />這星期試著測試 Gallery3, 發現這樣的設定還是會造成問題, 所以比較好的作法, 還是把它分成兩段來處理. 如:<p> </p><pre class="ini"><div class="insertcode"><pre class="ini" style="font-family: monospace">location ~ ^<span class="br0">(</span>?<SCRIPT>/.*\.<span class="br0">(</span>php|php3|phtml|suphp<span class="br0">)</span><span class="br0">)</span>$ <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /etc/php5/fpm/pool.d/$cur_php_user.conf<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url unix:/var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $cur_php_user <span class="st0">""</span><span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_param SCRIPT_NAME $SCRIPT<span class="co0">;</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$SCRIPT<span class="co0">;</span><br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /><span class="br0">}</span><br />location ~ ^<span class="br0">(</span>?<SCRIPT>/.*\.<span class="br0">(</span>php|php3|phtml|suphp<span class="br0">)</span><span class="br0">)</span><span class="br0">(</span>?<PATH_INFO>.*<span class="br0">)</span>$ <span class="br0">{</span><br /> uninitialized_variable_warn off<span class="co0">;</span><br /> if <span class="br0">(</span>$PATH_INFO <span class="sy0">=</span> <span class="st0">""</span><span class="br0">)</span> <span class="br0">{</span><br /> # avoid empty path_info<br /> set $PATH_INFO $SCRIPT<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $fpm_url unix:/var/run/php-fpm.sock<span class="co0">;</span><br /> if <span class="br0">(</span>-f /etc/php5/fpm/pool.d/$cur_php_user.conf<span class="br0">)</span> <span class="br0">{</span><br /> set $fpm_url unix:/var/run/php-fpm/$cur_php_user.sock<span class="co0">;</span><br /> <span class="br0">}</span><br /> set $cur_php_user <span class="st0">""</span><span class="co0">;</span><br /> fastcgi_index index.php<span class="co0">;</span><br /> include fastcgi_params<span class="co0">;</span><br /> fastcgi_param PATH_INFO $PATH_INFO<span class="co0">;</span><br /> fastcgi_param PATH_TRANSLATED $document_root$PATH_INFO<span class="co0">;</span><br /> fastcgi_param SCRIPT_NAME $SCRIPT<span class="co0">;</span><br /> fastcgi_param SCRIPT_FILENAME $document_root$SCRIPT<span class="co0">;</span><br /> fastcgi_pass $fpm_url<span class="co0">;</span><br /><span class="br0">}</span></pre></div></pre><p> </p><p> </p>
PHP
Nginx
2011-12-02T16:48:04Z
tommy