跳到主要內容

Nginx inside FreeBSD jail

Nginx inside FreeBSD jail

FreeBSD jail 類似 Linux 中的 KVM ,可以在同一個作業系統裡並存多個子系統,與虛擬機器的不同處在於這些子系統是共用同一份核心,因此佔用較少的硬體資源;通常這種子系統稱為容器 (container),除了用於沙箱實驗外,也常出現 service jail 的應用,可以想成是系統層級的 bundle 。

目標
使用 ezjail 設定與管理 jail
使用 pf.conf 設定 NAT 允許從外部存取 jail 內的 nginx
在 jail 中架設 nginx

Note
以下步驟需要使用 root 權限,或是另行安裝 sudo 。
文中以 host / jail 分別代表安裝 jail 的主系統jail 子系統
除了 ezjail 外其實有另一套 qjail ,這兩個之間似乎有點恩怨

Step 1. 安裝與初始化 (host)

# 取得 ezjail 套件。
pkg install -y ezjail
# 指定從何處取得佈署檔案,不給 -h 參數的話會從 ftp 取得,這邊我是從安裝光碟取得
ezjail-admin install -h file:///media/cdrom/usr/freebsd-dist

Optional: 啟用 ezjail 中的 zfs 支援 (host)

若你的 host 使用 zfs 的話,可以啟用 ezjail 中的相關選項讓 jails 使用 zfs 的 datasets

# 建立 zfs dataset 給 jail 用
zfs create zroot/usr/jails

編輯 /usr/local/etc/ezjail.conf

# ZFS options
# Setting this to YES will start to manage the basejail and newjail in ZFS 
ezjail_use_zfs="YES"
# Setting this to YES will manage ALL new jails in their own zfs
ezjail_use_zfs_for_jails="YES"
# The name of the ZFS ezjail should create jails on, it will be mounted at the ezjail_jaildir
ezjail_jailzfs="zroot/usr/jails"

Step 2. 建立 jail (host)

ezjail-admin create www 10.1.1.1

剛建立好的 jail 還需要設定網路環境才能從外部存取。

Step 3. 設定網路 (host)

每一個 jail 都需要一個固定 IP ,這裡採用建立新的 local network (lo1) 的方式,可移植性較佳。

編輯 /etc/rc.conf

# 給所有 jail 使用的介面 (不可與其它介面重複)
cloned_interfaces="lo1"
ifconfig_lo1="inet 10.1.1.1 netmask 255.255.255.0"

# 額外的 jail 使用同一介面的別名 (alias) ,注意遮罩設定為 255.255.255.255
# ifconfig_lo1_alias0="inet 10.1.1.2 netmask 255.255.255.255"

# 啟用 NAT 與 packet filter
pf_enable="YES"
pf_rules="/etc/pf.conf"

# 開機時啟動 jail
ezjail_enable="YES"

新增介面 lo1

% ifconfig lo1 create
% ifconfig lo1 inet 10.1.1.1 netmask 255.255.255.0

編輯 /etc/pf.conf

# 介面,用 ifconfig 查看對外介面 (external interface, ext_if) 的名稱,我的是 em0
ext_if="em0" 
int_if="lo1"
jailnet= $int_if:network

# NAT 允許從 jailnet 到 ext_if 的傳輸
nat on $ext_if from $jailnet to any -> ($ext_if)
# port forwarding
# www 是我們支後要建立的 jail 名稱,IP 則是前面指定過的
www="10.1.1.1"
# 允許 HTTP/HTTPS 的傳輸
rdr pass on $ext_if inet proto tcp to port http -> $www port http
rdr pass on $ext_if inet proto tcp to port https -> $www port https

接著就重新啟動吧!

Step 4. 設定 jail 內部環境 (jail)

使用 jls 查看有哪些 jail 跑起來

% jls
   JID  IP Address      Hostname                      Path
     1  10.1.1.1        www                           /usr/jails/www

進入 jail

% jexec www tcsh

編輯 /etc/resolv.conf

nameserver 8.8.8.8

這時候應該可以從 jail 裡面存取外部網路了,用 host 檢查一下

% host freebsd.org
freebsd.org has address 8.8.178.110
freebsd.org has IPv6 address 2001:1900:2254:206a::50:0
freebsd.org mail is handled by 10 mx1.freebsd.org.

Step 5. 安裝 nginx (jail)

使用 pkg 安裝 nginx

% pkg install -y nginx

編輯 /etc/rc.conf

nginx_enable="YES"

離開 jail 並重新啟動所有 jails

% exit
# this will block if any other session is attached to a jail via jexec
% service ezjail restart 

Step 6. 測試(host)

% curl 10.1.1.1 # 也可以找不同網域的機器嘗試存取,記得 IP 須換成 host IP
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

結論

目標
使用 ezjail 設定與管理 jail
使用 pf.conf 設定 NAT 允許從外部存取 jail 內的 nginx
在 jail 中架設 nginx

以上目標達成!

為了一個簡單的 web service 使用 jail 看似多餘,但是當額外的應用越來越多,比如架設一些應用性的服務、資料庫等等,維護套件相依性的問題就會越來越複雜,jail 讓我們得以把需要的套件區隔開來,尤其再遇到套件版本問題時,jail 的好處就更加顯著。

Future Work

  • Bugzilla in Jail (postgresql/nginx)
  • Jail backup/migration

Written with StackEdit.

留言

這個網誌中的熱門文章

得利油漆色卡編碼方式

得利油漆色卡編碼方式 類似 Munsell 色彩系統 ,編碼方式為 HUE LRV/CHROMA 例如 10GY 61/449 ( 色卡 ) 編碼數值 描述 10GY hue ,色輪上從 Y(ellow) 到 G(reen) 區分為 0 ~ 99 ,數值越小越靠近 Y,越大越靠近 G 61 LRV (Light Reflectance Value) 塗料反射光源的比率,數值從 0% ~ 100% ,越高越亮,反之越暗,也可理解為明度 449 chroma 可理解為彩度,數值沒有上限,越高顏色純度 (濃度) 越高 取決於測量儀器,對應至 RGB 並不保證視覺感受相同。 參考資料: 色卡對照網站 e-paint.co.uk Written with StackEdit .

UTF8 與 Unicode 的轉換 (C++)

UTF8 與 Unicode 的轉換 (C++) 先釐清一下這兩者的性質 Unicode: 為世界上所有的文字系統制訂的標準,基本上就是給每個字(letter)一個編號 UTF-8: 為 unicode 的編號制定一個數位編碼方法 UTF-8 是一個長度介於 1~6 byte 的編碼,將 unicode 編號 (code point) 分為六個區間如下表 1 Bits First code point Last code point Bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 7 U+0000 U+007F 1 0xxxxxxx 11 U+0080 U+07FF 2 110xxxxx 10xxxxxx 16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx 21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 觀察上面的表應該可以發現 除了 7 bits 的區間外,第一個 byte 開頭連續 1 的個數就是長度,例如 110XXXXX 就是 2 byte 長,而 1110xxxx 就是 3 byte 除了第一個 byte 外,之後的 byte 前兩個 bit 一定是 10 開頭,這樣的好處在於確立了編碼的 self-synchronizeing,意即當編碼為多個 byte 時,任取一個 byte 無法正常解碼。 Note 第一點中的例外 (7 bits) 是為了與 ASCII 的相容性,而第二點會影響到 code point 至 UTF-8 的轉換。 為了與 UTF-16 的相容性,在 R

C++17 新功能 try_emplace

C++17 新功能 try_emplace 回顧 emplace 大家的好朋友 Standard Template Library (STL) 容器提供如 push_back , insert 等介面,讓我們塞東西進去; C++11 之後,新增了 emplace 系列的介面,如 std::vector::emplace_back , std::map::emplace 等,差異在於 emplace 是在容器內 in-place 直接建構新元素,而不像 push_back 在傳遞參數前建構,下面用實例來說明: struct Value { // ctor1 Value ( int size ) : array ( new char [ size ] ) , size ( size ) { printf ( "ctor1: %d\n" , size ) ; } // ctor2 Value ( const Value & v ) : array ( new char [ v . size ] ) , size ( v . size ) { printf ( "ctor2: %d\n" , size ) ; memcpy ( array . get ( ) , v . array . get ( ) , size ) ; } private : std :: unique_ptr < char [ ] > array ; int size = 0 ; } ; struct Value 定義了自訂建構子 (ctor1),以指定大小 size 配置陣列,複製建構子 (ctor2) 則會配置與來源相同大小及內容的陣列,為了方便觀察加了一些 printf 。當我們如下使用 std::vector::push_back 時 std :: vector < Value > v ; v . push_back ( Value ( 2048 ) ) ; 首先 Value 會先呼叫 ctor1,傳給 push_ba