====== FreeBSD 11.1-RELEASEを自由なZFSパーティション構成でインストールする ======
bsdinstallの登場により、FreeBSD 10あたりからRoot on ZFSでのインストールが簡単に出来るようになった。
一方で、昔ながらの手動でRoot on ZFSを作っていたユーザーは、ZFSのファイルシステム構成やプロパティを自由に設定したいと考えるだろう。かくいう自分もその一人である。最近のFreeBSDのインストール作法を踏まえつつ、手動でZFSルートファイルシステムを作る方法が分かったので、備忘録も兼ねて記事にする。
===== 実現したいこと =====
* ストレージのパーティションの1つをルートプールとして使いたい!
* bsdinstallだとストレージ全体がzpoolにされてしまう…
* ストレージ全体を割り当てた場合、デバイスが死んだ際に交換先の容量誤差で交換できない可能性が微レ存…
* データセットの階層をデフォルトから変えたい!
* 標準インストールではプール直下に/usrとかが作られる(zroot/usr的な)けど、間に1つ階層を挟みたいんじゃー(zroot/sys/usr的な)
* プール直下だとsnapshotの扱いが面倒だったりする
* データセット作成時にしか指定できないプロパティを変更したい!
* utf8onlyで運用したいじゃん?
* compressionなんかも最初から有効にした方が効くじゃん?
* ストレージ構成以外はbsdinstallに任せたい!
* なんだかんだ言ってdialog(1)でIPアドレスとか設定できた方がが分かりやすいし…
* その時々の時流に応じてインストーラで設定出来ることが追加されてたりするし…
* 最近のインストーラではsendmailの無効化やPIDのランダム化が設定出来るようになっててびっくりしたよ
===== 試した環境 =====
* FreeBSD 11.0-RELEASE
* FreeBSD 11.1-RELEASE
* レガシーブート環境(非UEFIブート)
bsdinstall以降のリリースならどれにでも適用できると思われる。
===== 手順 =====
お作法は至ってシンプルで、インストール環境の/mnt=インストール先のルートディレクトリ(/)となるように、ファイルシステムを作ってマウントしてあげれば良い。あとはbsdinstallが全部やってくれる。
操作は全てインストーラのシェルで行う。
{{ :freebsd:install:freebsd_installer_fall_down_to_shell.png |}}
==== ZFSモジュールを読み込む ====
# kldload zfs
実はzpool, zfsコマンドを実行した時に勝手にロードされるんだけど、モジュールを読み込んでおかないと次に設定する4kセクタ用のカーネル変数が生えてこないのである。
==== ルートプールを作る準備 ====
ZFSのプールを4kセクタで作るためのおまじない
# sysctl vfs.zfs.min_auto_ashift=12
vfs.zfs.min_auto_ashift: 9 -> 12
ディスク全体の以前のZFS情報を消す
# zpool labelclear -f da0
HDDのパーティションを切る
ここはお好みで。将来のUEFIブート移行を見越してESPを確保してある。またスワップは専用パーティションにしたい派。
# gpart create -s gpt da0
# gpart add -a 4k -t efi -s 512m da0
# gpart add -a 4k -t freebsd-boot -s 512k da0
# gpart add -a 4k -t freebsd-zfs -s 30g da0
# gpart add -a 4k -t freebsd-swap -s 16g da0
# gpart add -a 4k -t freebsd-zfs -s 40g da0
確認
# gpart show da0
=> 40 195312424 da0 GPT (93G)
40 1048576 1 efi (512M)
1048616 1024 2 freebsd-boot (512K)
1049640 62914560 3 freebsd-zfs (30G)
63964200 33554432 4 freebsd-swap (16G)
97518632 83886080 5 freebsd-zfs (40G)
181404712 13907752 - free - (6.6G)
パーティション毎の以前のZFS情報を消す([[blog:2017:2017-11-09|念の為]])
# zpool labelclear -f da0p1
# zpool labelclear -f da0p2
# zpool labelclear -f da0p3
# zpool labelclear -f da0p4
==== ルートプールの作成 ====
ルートプールを作る
デフォルトインストーラによるプロパティの設定はcompressionとatimeのみ。他のプロパティや値はご自由に。
# zpool create -o altroot=/mnt -o cachefile=/tmp/zpool.cache -O mountpoint=none -O compression=lz4 -O atime=off -O normalization=formC zroot da0p3
4kセクタで作られたか確認
# zdb -U /tmp/zpool.cache | grep ashift
ashift: 12
各種ZFSファイルシステムを作る
デフォルトのプロパティ設定は「[[blog:2017:2017-10-18]]」を参照してくだしあ。
デフォルトシステムのFSを作成。
zfs create -o mountpoint=/ -o canmount=noauto -p zroot/sys/ROOT/default
zfs mount zroot/sys/ROOT/default
最近のFreeBSD on ZFSでは、Solaris由来の[[https://www.freebsd.org/cgi/man.cgi?beadm|Boot Environment]]という考えを意識しているようで、ルートプールのbootfsで指定したFS──デフォルトではzroot/ROOT以下の複数のシステムをブート時に切り替えられるようになっている。zroot/ROOT/defaultというのは、その名の通りデフォルトのシステムが入ることになる。
これらシステムFSのcanmountはnoautoになるので、自動マウントは行われない。起動時に選択されたシステムはブートローダによって、設定されたmountpoint、つまりルートディレクトリにマウントされることでアクティブなシステムとなる仕組み。
後続のFS作成のため、作成後は必ずzfs mountすること。インストーラ環境の/mntは読み込み専用となっているため、作成したインストール先でオーバーレイしてやらないと、後続のFS作成時にマウントポイントが作れないエラーになる。
その他、必要なFSを作る。
zfs create -o mountpoint=/tmp -o exec=on -o setuid=off zroot/sys/tmp
zfs create -o mountpoint=/usr -o canmount=off zroot/sys/usr
zfs create -o mountpoint=/usr/ports -o compression=gzip-9 -o setuid=off zroot/sys/usr/ports
zfs create -o mountpoint=/usr/src -o compression=gzip-9 zroot/sys/usr/src
zfs create -o mountpoint=/var zroot/sys/var
zfs create -o mountpoint=/var/audit -o exec=off -o setuid=off zroot/sys/var/audit
zfs create -o mountpoint=/var/crash -o exec=off -o setuid=off zroot/sys/var/crash
zfs create -o mountpoint=/var/log -o exec=off -o setuid=off zroot/sys/var/log
zfs create -o mountpoint=/var/mail -o atime=on zroot/sys/var/mail
zfs create -o mountpoint=/var/tmp -o setuid=off zroot/sys/var/tmp
/usrがcanmount=offであることに注意。
これらFSは上述のROOT/defaultのマウント後にオーバーレイ的にマウントされ、/以下はzpool/ROOT/defaultとzroot/usr等が重なり合い入り混じった状態となる。この辺は従来のUFSと大きく違う所なので、よーく理解しておく必要がある。UnionFSの挙動に近いかも?
ホームディレクトリは別プールに起きたいので作成。ルートプールのままでいいなら、ルートプールに作って下しあ。
zpool create -o altroot=/mnt -O mountpoint=legacy -O compression=lz4 -O atime=off -O normalization=formC zdata da0p5
zfs create -o mountpoint=/usr/home -p zdata/ROOT/home
パーミッションの設定
chmod 1777 /mnt/tmp
chmod 1777 /mnt/var/tmp
==== FSの確認とブートコードの書き込み ====
ZFSが以下のような感じで作られマウントされてればOK。重要なのはzroot/ROOT/defaultに相当するFSが/mntにマウントされていること、zroot/usr等が/mntをルートとしてマウントされていること。
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
zdata 516K 38.5G 96K /mnt/zdata
zdata/ROOT 192K 38.5G 96K /mnt/zdata/ROOT
zdata/ROOT/home 96K 38.5G 96K /mnt/usr/home
zroot 2M 28.8G 96K none
zroot/sys 1.23M 28.8G 96K none
zroot/sys/ROOT 192K 28.8G 96K none
zroot/sys/ROOT/default 96K 28.8G 96K /mnt
zroot/sys/tmp 96K 28.8G 96K /mnt/tmp
zroot/sys/usr 288K 28.8G 96K /mnt/usr
zroot/sys/usr/ports 96K 28.8G 96K /mnt/usr/ports
zroot/sys/usr/src 96K 28.8G 96K /mnt/usr/src
zroot/sys/var 584K 28.8G 104K /mnt/var
zroot/sys/var/audit 96K 28.8G 96K /mnt/var/audit
zroot/sys/var/crash 96K 28.8G 96K /mnt/var/crash
zroot/sys/var/log 96K 28.8G 96K /mnt/var/log
zroot/sys/var/mail 96K 28.8G 96K /mnt/var/mail
zroot/sys/var/tmp 96K 28.8G 96K /mnt/var/tmp
=== MBR用ブートコードの設定 ===
zpool set bootfs=zroot/sys/ROOT/default zroot
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 2 da0
=== EFI用ブートローダの設定 ===
ESPをFATでフォーマットして/tmp/espにマウント。
# newfs_msdos -F 32 da0p1
# mkdir /tmp/esp
# mount -t msdosfs /dev/da0p1 /tmp/esp
「newfs_msdos: 32750 clusters too few clusters for FAT32, need 65525」って感じのエラーになるときは、newfs_msdosでセクタサイズ/クラスタサイズを明示的に指定してやる。条件はよくわからないが、16KiBクラスタとかでフォーマットしようとする事があるっぽい。
# newfs_msdos -F 32 -S 512 -c 4 da0p1
-Sがセクタサイズ(バイト)で、-cがクラスタサイズ(セクタ数)を表す。上記例だと1クラスタ=512バイトセクタ×4=4096バイト、ということになる。
ブートローダをコピー
# mkdir -p /tmp/esp/efi/boot
# cp /boot/boot1.efi /tmp/esp/efi/boot/BOOTx64.efi
(2021-01-12追記) \\
以前の説明ではESPにloader.rcを作っていたが、効果がないので記述を削除。また、12.0-RELEASEからBOOTx64.efiとしてboot1.efiに代わってloader.efiが使われるようになっている。
ファイルが正しい場所にあるか確認
# ( cd /tmp/esp && find . )
.
./efi
./efi/boot
./efi/boot/BOOTx64.efi
最後に必ずアンマウントする
# umount /tmp/esp
==== FreeBSD Installerでシステムをインストール ====
ここまで来たら終ったも同然。shellをexitし、通常のインストール手順で「Partitioning」まで進める。
{{ :freebsd:install:freebsd_installer_partitioning_by_shell.png |}}
「Shell」に入り、そのままexitするとシステムのインストールが行われる。
{{ :freebsd:install:freebsd_installer_archive_extraction.png |}}
タイムゾーンやデフォルトのデーモンの設定なども通常通り行い、最後の「Manual Configuration」でシェルに入り、最後の仕上げをする。
{{ :freebsd:install:freebsd_installer_manual_configuration.png |}}
シェルの先頭メッセージにある通り、インストール先ディレクトリにchrootした状態、つまりインストーラ環境の/mntが/になっているので注意。
=== スワップの設定 ===
# vi /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/da0p4 none swap sw 0 0
/boot/loader.confの設定
# echo 'zfs_load="YES"' >> /boot/loader.conf
/etc/rc.confの設定
# echo 'zfs_enable="YES"' >> /etc/rc.conf
==== 動作確認 ====
設定が全て終わったらシェルをexitしてRebootする。
再起動後、無事ログインプロンプトが出ればひとまず成功。まずはrootでログインし、ファイルシステム群が想定通りにマウントされているか十分に確認すること。特にホームディレクトリを別プールとした場合は、/usr/homeが正常に機能しているか確認してくだしあ。
お疲れ様でした。
===== 雑多なメモ =====
* FreeBSD 8.3-RELEASEから、デフォルトchecksumはfletcher4になったので、今や明示的に指定する必要はない。
* vfs.root.mountfromによるルートプールの設定も必要なくなったっぽい。
===== 参考サイト =====
* [[https://qiita.com/kunst1080/items/80829f2d4e6478831b28|bsdinstallを使用したFreeBSDの自動インストールについて - Qiita]]
* [[http://zenno.com/pukiwiki/index.php?FreeBSD%2FUEFI%A4%CB%A4%C4%A4%A4%A4%C6|FreeBSD/UEFIについて - PukiWiki]]
* [[http://zenno.com/pukiwiki/index.php?FreeBSD%2F%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%EB10.3%28UEFI%29|FreeBSD/インストール10.3(UEFI) - PukiWiki]]
* [[https://www22.atwiki.jp/lud-p/pages/27.html|FreeBSD/Install FreeBSD 10.2-Release on pure ZFS - ルドP@wilog - アットウィキ]]
* [[https://savagedlight.me/2016/02/02/venus-semi-manual-freebsd-11-current-amd64-zfsuefi-installation/|Venus: Semi-Manual FreeBSD 11-CURRENT AMD64 ZFS+UEFI Installation | Savagedlight's Road]]