NanoBSD


文件更新日期: 2014/11/22

Why NanoBSD??

就我僅知的, 要把 FreeBSD 作成嵌入式系統的 OS 有三種手法, 最早得知的是 PicoBSD, 然後是 TinyBSD, 還有最近才開始碰的 NanoBSD. 因為系統的需求, 我需要把功能完整而且包含 Ports 的 FreeBSD 搞成嵌入式系統(裝在 CF 卡裡面), 系統基本功能拿 PicoBSD 或 TinyBSD 都很簡單, 但是要包含 Ports 的話則是 NanoBSD 比較容易.

1. 事前準備
先要有一台對應版本的 FreeBSD box(廢話!?), 我用的是 FreeBSD 7.1(目前測試 7.2~9.2 都 ok, 這東西已經進 system source, 所以應該不會出什麼大問題)

1-1. 把預定要安裝的 ports 做成 package
mkdir /usr/ports/packages
cd /usr/ports/ooxx
make DEPENDS_TARGET=package package clean

這個步驟大概會耗掉非常多時間, 所以如果是機器上已經裝好了的東西, 可以直接用 pkg_create -b 包 package, 可以省下非常多的時間.

如果是要升級現有的 ports, 可以跑 portmaster -abd 直接升級 ports 順便包出 package.

(2014/04/23追加)
2014/09/01 以後 package 管理系統會完全轉換到 pkgng, 原本的 pkg_create 就不能用了, 新的包 package 指令是 pkg create -a, 可以一次把機器上的 ports 全部包成 package.

(2014/05/12追加)
目前 9.x 系統裡的 nanobsd.sh 並不相容新版的 pkgng, 所以請先不要換成 pkgng, 不然到了 裝 package 這一步就會慘死.

(2014/05/14追加)
雖然說還沒有幾個月就要換成 pkgng 了, 可是 src 裡面的 nanobsd.sh 到目前為止還是沒更新, 所以得要自己改 (以下是 9.2 Release 的 diff, 10.0 的內容也差不多, 改一改就可以上)
--- nanobsd.sh    2013-09-27 07:40:02.000000000 +0800
+++ nanobsd.sh.new 2014-05-14 09:26:22.000000000 +0800
@@ -706,18 +706,17 @@
     while true
     do
         # Record how many we have now
-        have=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
+        have=`pkg -c ${NANO_WORLDDIR} info | wc -l`

         # Attempt to install more packages
         # ...but no more than 200 at a time due to pkg_add's internal
         # limitations.
-        chroot ${NANO_WORLDDIR} sh -c \
-            'ls Pkg/*tbz | xargs -n 200 pkg_add -F' || true
+        (cd ${NANO_WORLDDIR} && ls Pkg/*txz) | xargs -n 1 pkg -c ${NANO_WORLDDIR} add || true

         # See what that got us
-        now=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
+        now=`pkg -c ${NANO_WORLDDIR} info | wc -l`
         echo "=== NOW $now"
-        ls ${NANO_WORLDDIR}/var/db/pkg
+        pkg -c ${NANO_WORLDDIR} info
         echo "==="
(2014/11/22追加)
10.1 RELEASE 的 nanobsd.sh 完全支援 pkgng 了, 可喜可賀


把 packages 目錄 link 到 nanobsd 目錄底下
cd /usr/src/tools/tools/nanobsd
ln -s /usr/ports/packages/All Pkg


1-2. 準備好預定要用的 kernel config
這邊要注意, 因為 kernel modules 有很多用不上的東西會佔掉寶貴的儲存空間, 所以要把所有用得到的功能通通編進 kernel 裡面去.

1-3. 準備好預定要用的設定檔
NanoBSD 在製作時會讀取放在 /usr/src/tools/tools/nanobsd/Files 的設定檔, 要放進預設系統的設定檔就照原有的檔案結構把設定檔放進去即可. (如果是往後會更改的設定, 可以等系統設定好再放)
假設是 /usr/local/etc/apache/httpd.conf
就放在 /usr/src/tools/tools/nanobsd/Files/usr/local/etc/apache/httpd.conf
Files 底下預設會有個 root 目錄, 裡面的4個檔案是日後供管理和升級用的 script

2. 製作 NanoBSD
NanoBSD 的位置在 /usr/src/tools/tools/nanobsd, 全部的設定都放在底下的 nanobsd.sh 裡面, 要更改的設定和參數建議用另一個檔案儲存. (最好不要直接去改 nanobsd.sh, 不然日後 cvsup 可能會有問題, 我放在 CFBSD.conf)

2-1. 更改 NanoBSD 的編譯設定
以下是我的設定檔 CFBSD.conf 更改的部分, 功能部分可以看 nanobsd.sh 自己新增或更改
a. 設定 NanoBSD image 的名字(編譯完成的檔案會在 /usr/obj/nanobsd.CFBSD/)
NANO_NAME=CFBSD

b. 設定 CF 卡的大小 (單位是 512byte/block)
NANO_MEDIASIZE=2000000

c. 設定 make 的選項(可以機器狀況調整)
NANO_PMAKE="make -j 5"

d. 設定編譯時的選項 (for buildworld only)*
CONF_BUILD='
NO_KLD_LOAD=YES
NO_NETGRAPH=YES
NO_PAM=YES
PPP_NO_NETGRAPH=YES
PPP_NO_RADIUS=YES
'


e. 設定編譯時的選項 (for installworld only)*
CONF_INSTALL='
NO_AUTHPF=YES
NO_BLUETOOTH=YES
NO_CVS=YES
NO_DICT=YES
NO_FORTRAN=YES
NO_GDB=YES
NO_HTML=YES
NO_LPR=YES
NO_PROFILE=YES
NO_SENDMAIL=YES
NO_SHAREDOCS=YES
NO_EXAMPLES=YES
NO_INSTALLLIB=YES
NO_CALENDAR=YES
NO_MISC=YES
NO_MAKE=YES
'


f. 設定編譯時的選項 (for both build- & installworld)*
CONF_WORLD='
NO_ATM=YES
NO_I4B=YES
NO_INET6=YES
NO_NIS=YES
NO_RCMDS=YES
NO_GAMES=YES
NO_RESCUE=YES
PPP_NO_NETGRAPH=YES
PPP_NO_RADIUS=YES
NO_LOCALS=YES
NO_NLS=YES
NO_PCVT=YES
NO_IPX=YES
NO_INFO=YES
'


g. 設定 kernel config (檔案位置照系統預設值 /usr/src/sys/i386/conf 即可)
NANO_KERNEL=CFBSD

h. 設定 NanoBSD 開機用的硬碟代號
NANO_DRIVE=ad0

i. 設定 /cfg 的檔案系統大小 (單位是 512byte/block)
NANO_CONFSIZE=40960

j. 設定 /etc 用的 ramdisk 的大小 (單位是 512byte/block)
NANO_RAM_ETCSIZE=131072

k. 設定 /tmp 和 /var 用的 ramdisk 的大小 (單位是 512byte/block)
NANO_RAM_TMPVARSIZE=262144

l. 新增一個函數 cust_fix_usr_local , 把 /usr/local/etc 放到/etc/local, 以便日後更改相關設定用(
(FreeBSD 8.0 以後的 nanobsd.sh 已經內建這個功能, 如果是用 8.x 請跳過這一步)
cust_fix_usr_local() (
mkdir ${NANO_WORLDDIR}/etc/local
cp -R ${NANO_WORLDDIR}/usr/local/etc/* ${NANO_WORLDDIR}/etc/local
rm -r ${NANO_WORLDDIR}/usr/local/etc
#rmdir ${NANO_WORLDDIR}/usr/locla/etc
chroot ${NANO_WORLDDIR} sh -c 'ln -s /etc/local /usr/local/etc'
)



m. 安裝 packages
customize_cmd cust_pkg

n. 讀入 Files/root 底下的設定檔
customize_cmd cust_install_files

o. 利用剛才新增的函數把 usr/local/etc 改到 etc/local
customize_cmd cust_fix_usr_local

p. 讓 root 可用 ssh 登入 (非必要)
customize_cmd cust_allow_ssh_root

2-2. 編譯 NanoBSD
NanoBSD 的系統內容是以現有的 FreeBSD box 為基礎, 所以會 make buildworld && buildkernel , 相當耗時, 但是為了日後有完整的功能可以用, 只能等等等等等...
sh /nanobsd.sh -c CFBSD.conf



2-4. 安裝 NanoBSD 到 CF 卡上
編譯完成後的 disk image 會放在 /usr/obj/nanobsd.CFBSD/_.disk.full, 用 dd 直接寫到 CF 卡(假設是ad2)上
dd if=_.disk.full of=/dev/ad2 bs=64k


2-5. 把 CF 裝到機器上, 開機測試

3. 安裝後的設定
安裝進 CF 並確定可以開機正常運作之後, 就要來處理設定檔的部分了

3-1. 更改 NanoBSD 的設定檔
NanoBSD 開機時會讀取 /cfg 底下的設定檔, 平常運作時 /cfg 預設是 umount 的, 基本設定則放在 /conf 底下. 由於檔案系統都是 read-only, 所以改完以後記得把 /etc 的設定檔 cp 到 /cfg, 下次開機才會生效. (不用再建 /cfg/etc 目錄, 預設就是用 /cfg 蓋過 /etc)
/cfg 預設是可讀寫的, 要改的時候再 mount, 平常則保持 umount 狀態.

3-2. 其他設定
/root 底下有個 save_sshkeys 的 script, 可以幫忙把開機時產生的 ssh keypair 存進 /cfg, 這樣就不用每次開機時去重新產生 keypair, 也不會有 ssh 連線時每次 key 都不一樣的問題. 另一個 change_passwd 則是更改 root 密碼用的, 一樣會自動把更新完的檔案放到 /cfg
如果有安全性的疑慮, 在當初製作 image 時就把 script 拿掉就好了.

4. 升級 NanoBSD

4-1. 編譯新版 NanoBSD
基本上就是照 2-2 再跑一遍, 不過 nanobsd.sh 裡面提供了一些有用的選項, 可以省下一點時間:
-k 跳過 buidkernel, 只跑 buildworld
-w 跳過 buildworld, 只跑 buildkernel
-b 跳過 buildworld && buildkernel (只是升級 Ports 的話就用這個)

4-2. 安裝新版 NanoBSD
NanoBSD 預設會安裝兩個系統進去 (換句話說 CF 裡面會有一組備份系統)
之前 NanoBSD 在編譯完成後會有兩個檔案: _.disk.fill 和 _.disk.image, 後者 (_.disk.image)就是升級用的. 如果之前有下 cust_install_file 把 Files 底下的檔案裝進去的話, 應該可以找到 updatep1 和 updatep2 兩個 script, 分別是更新 CF 上的 OS#1 或 OS#2 用的 (請記住要更新的是哪一個).

官方 NanoBSD Howto 介紹的更新方式有 3 種, 分別是利用 ftp, ssh 以及 nc, 我是比較喜歡用 nc, 反正都躲在防火牆裡面不會有什麼 security issue, 沒必要用到 ssh.

4-2-1. 更新用 image 來源設定
首先在編譯用的機器(NanoMOM)上把 image 給開放出來(記得是在編譯用的機器上, 不是 NanoBSD 主機), 我設定使用 port 2048 丟出去
nc -l 2048 < _.disk.image

4-2-2. 更新 NanoBSD
接下來就 login 到 NanoBSD 主機上, 執行以下的指令
(假設是更新 OS#1, 所以用的是 updatep1)
nc NanoMOM 2048 | sh updatep1
 (8.3 Release 開始多了個會自動選擇未使用 OS 的 script 叫 update, 不需要自己選了)


如果要改用 ssh 的話, 先確定機器上的 sshd 有開, 然後執行以下的指令
ssh NanoMOM cat _.disk.image.gz | zcat | sh updatep1

跑完以後就更新完成, 這個 script 會把開機選用的 OS 設定成剛剛更新的 image, 所以只要 reboot 就是用新系統在跑了.

(2009/11/12)
目前跑起來有些小問題, 就是關於系統更新的部分.
內建的 script 會跑 boot0cfg 來設定 CF 上面的 active partition 是哪個, 但是目前我的機器上卻沒有變更 active partition, 必須要自己手動用 fdisk 來改, 不知道是不是 7.2R 的問題... 換成 8.x 以後就沒有這個問題了.



*: 注意不要把太多東西給拿掉, 不然到時候有東西不能跑就糗了.

2 則留言:

  1. 請問您有遇過/cfg預設為ro的嗎?要怎麼讓/cfg變成rw呢?

    回覆刪除
  2. 我沒遇過這種問題, nanobsd.sh裡面預設/cfg是rw.

    預設值請看/conf/base/etc/fstab, 如果這邊是rw那就是你的/cfg/fstab寫錯,改掉就好了.

    回覆刪除