Integration by me

你們必曉得真理,真理必叫你們得以自由。

標籤:nginx

讓 nginx 重定向遵循 HTTP

根據 RFC 2616,除了 Location 標頭外,回覆實體(也就是一般使用者看到的網頁)裡面也需要包含重定向的目標。不過基於程式的健壯性原則,瀏覽器等 user agents 會選擇只看 Location,而且從網頁中找尋正確的連結對程式來說比較困難。然而,一般使用者還是有機會看到重定向的網頁,例如重定向失敗1的時候。

不過 nginx 的錯誤頁面(狀態碼 ≥ 300)其實都沒有附連結。以 302 重定向為例:

幸好 nginx 可以讓我們自訂錯誤頁面,並且支援 SSI。所以我就自己寫了重定向頁面。這樣就有符合 HTTP 標準的重定向頁面了。

該頁面已經搬家囉!
==================
它的新家在 <a href='<!--# echo var="sent_http_location" -->'><!--# echo var="sent_http_location" --></a>
  1. 依規定 301, 302 重定向只接受 GET 和 HEAD,因此以其他請求方式就會停在回覆實體。 

在 nginx 上調整所有文本的編碼

全站的文字檔都使用相同編碼是很常見的。尤其是 UTF-8 儼然是今日的實作標準。然而,nginx 預設的 charset_types 設定不包括 text/css,遑論其他非純文本。(例如 text/markdown

預設的 charset_types 應該要是 text/* 才對,因為為了向後相容,許多 text/* 格式預設解讀為 ASCII (us-ascii)。就連 text/xml 也是如此,即使檔案中有 BOMXML 宣告也徒勞無功。所以,現在我們應該用 application/xml 來傳遞 XML。

然而 charset_types 設定只檢查完全符合的 MIME,不然就必須用 * 匹配所有類型。幸好 nginx 有可以匹配正則表達式的 map,而且 charset_types 也接受變數。

map $sent_http_content_type $charset {
    ~^text/   utf-8;
}

charset       $charset;
charset_types *;

這樣的設定會讓 nginx 指定所有文本為 UTF-8,例如 text/css; charset=utf-8

貼圖討論版開張

在同學的慫恿下,我架了貼圖討論版源碼擺在 GitHub 讓全世界幫我備份。不過目前我提交的多已匯入 vichan 主線。請下載官方版以獲得其他人的本月貢獻。

[同學……等等,你不是唸醫學系嗎?先承認你就是你同學!] [阿就真的偶同學咩!]

技術細節

它採用 vichan,是一款高效能的貼圖討論版程式。它的特點是在伺服器上產生靜態的網頁、資源,因此能應付高流量。

目前中文化已進入 beta 階段,也就是已完成,但還可能有些 bugs

而為了好好利用 nginx 的 gzip_static 模組,我在 inc/functions.php 加了一段程式碼,讓它在寫檔的時候順便產生 .gz 檔。

此外,為了在行動裝置上有較好的表現,我在內建佈景中設定 viewport

Tinyboard/vichan 的特點

Tinayboard 給閱聽人跑的程式只有 post.php 一支,給職員的只有 mod.php 一支,其他都是靜態資源。他們只在閱聽人貼文及職員修改設定時重建 (rebuild) 網站⸺重新產生靜態網頁。職員在修改設定時,可能因為網站未重建,新設定尚未生效。職員可於 GET /mod.php?/rebuild 的頁面中重建網站,讓閱聽人看見更新的資源。

給 nginx 和 php-fpm 的 AppArmor 設定檔

AppArmor 是 Ubuntu 預設的 MAC 模組。不像傳統 Unix 的 DAC,AppArmor 設定檔列出什麼是行程存取的。處於強制模式 (enforced) 的行程只能存取已列舉的路徑。處於抱怨模式 (complaining)

然而 nginxphp-fpm 沒有預設的設定檔。為了避免網頁伺服器遭駭造成系統性感染,自己的設定檔自己寫!我們有 aa-genprof 這個有用的工具完成大部份的工作,但是它還是會遺漏一些路徑,特別是 sockets。因此我把我的設定檔放上來作為他山之石。

以下是 nginx 的設定檔。

#include <tunables/global>

/usr/sbin/nginx {
	#include <abstractions/apache2-common>
	#include <abstractions/base>
	#include <abstractions/nis>

	capability dac_override,
	capability net_bind_service,
	capability setgid,
	capability setuid,

	/etc/nginx/** r,
	/etc/ssl/openssl.cnf r,
	/proc/*/auxv r,
	/run/nginx.pid rw,
	/run/nginx.pid.oldbin w,
	/run/php5-fpm.sock rw,
	/srv/www/** r,
	/usr/sbin/nginx mr,
	/var/log/nginx/* w,
}

以下是 php-fpm 的設定檔。

#include <tunables/global>

/usr/sbin/php5-fpm {
	#include <abstractions/base>
	#include <abstractions/nameservice>
	#include <abstractions/php5>

	capability kill,
	capability setgid,
	capability setuid,

	/etc/php5/** r,
	/proc/*/auxv r,
	/proc/sys/kernel/ngroups_max r,
	/run/mysqld/mysqld.sock rw,
	/run/php5-fpm.pid rw,
	/run/php5-fpm.sock w,
	/srv/www/** r,
	/srv/www/html/wp-content/** rw,
	/srv/www/html/wp-content/cache/** rwk,
	/srv/www/magento/media/** rw,
	/srv/www/magento/var/** rwk,
	/tmp/ r,
	/tmp/** rwk,
	/usr/sbin/php5-fpm mrix,
	/var/log/php5-fpm.log* w,
}