Ubuntu (MBR) root on ZFS

自宅の HDD で動いていた Linux PC が飛んでしまったので、Ubuntu 24.04 サーバー を ZFS にしてインストールしてみました。

参考にしたサイト

OpenZFS Ubuntu 22.04 Root on ZFS(本家のサイトですが Ubuntu 22.04 の記述に注意です)

Ubuntu24.04 で root on ZFS を構築された方がいらっしゃいましたので、参考にさせていただきました。

古すぎてUSBブートできないPC

HDD で動作するPCにUbuntu 24.04 をインストールすることにしました。本家サイトを参照したら構築時に Legacy BIOS (MBR) と UEFI で異なることが分かりましたので PC 起動時に確認したら BIOS (MBR) でした。

また、USB ブートに対応していないことは以前から分かっていましたので、Ubuntu 24.04 のインストールは自ずと DVD に収まるサーバーイメージになりました。デスクトップインストーラーは手軽にZFSを選択できますが、サーバーであるため手操作のインストールとなりました。

Legacy BIOS と UEFI の違い

grub に関わる箇所が Legacy BIOS と UEFI の違いが表れるところになります。

構築手順

次から構築手順を記載しています。

サーバーイメージ DVD boot と SSH 接続準備

  • ubuntu-24.04.2-live-server-amd64.iso をダウンロードしてDVDからブートします。
  • Shell 起動とSSH準備
    DVD のインストーラー起動時に CTRL+Z または、右上の HELP から Shell へ入ります。SSHで接続しやすいようにユーザー追加とroot パスワードを設定しました。
$ adduser ichino
(ichino のパスワード等の設定)
$ passwd root
(root パスワードの設定)

SSH 端末からのインストール

  • SSH で接続する理由
    SSHの画面からコマンドラインをコピペすることが目的です。特に zpool のコマンド入力ではコピペしたくなります。従って、以降のコマンドラインではプロンプト表示を省略しています。
  • リポジトリ準備などの実施
apt update
apt purge needrestart
apt install --yes debootstrap gdisk zfsutils-linux
systemctl stop zed
  • パーティション設定
    ここは MBR を意識した設定を行います。
    参照先のサイトで blkdiskcard を用いていますが、HDDのため使用しません。
DISK=/dev/disk/by-id/ata-WDC_WD10EZRX-00L4HB0_WD-WCC4J2896427
swapoff --all
wipefs -a $DISK
sgdisk     -n1:2M:+512M   -t1:EF00 $DISK
sgdisk     -n2:0:+32G     -t2:8200 $DISK
sgdisk     -n3:0:+4G      -t3:BE00 $DISK
sgdisk     -n4:0:0        -t4:BF00 $DISK
  • gdisk を使って、結果的に先頭からHDD 先頭1M をブート用に割り当てますが、パーティション番号は5番を割り当てました。
gdisk $DISK
GPT fdisk (gdisk) version 1.0.10

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): n
Partition number (5-128, default 5):
First sector (34-4095, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-4095, default = 4095) or {+-}size{KMGTP}: +1M
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):EF02
Changed type of partition to 'BIOS boot partition'

Command (? for help):w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N):Y
  • 参照先サイトにあるコマンド順で入力する
zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -o cachefile=/etc/zfs/zpool.cache \
    -o compatibility=grub2 \
    -o feature@livelist=enabled \
    -o feature@zpool_checkpoint=enabled \
    -O devices=off \
    -O acltype=posixacl -O xattr=sa \
    -O compression=lz4 \
    -O normalization=formD \
    -O relatime=on \
    -O canmount=off -O mountpoint=/boot -R /mnt \
    bpool ${DISK}-part3

zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -O acltype=posixacl -O xattr=sa -O dnodesize=auto \
    -O compression=lz4 \
    -O normalization=formD \
    -O relatime=on \
    -O canmount=off -O mountpoint=/ -R /mnt \
    rpool ${DISK}-part4

zfs create -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o canmount=off -o mountpoint=none bpool/BOOT

データセットの生成ですが UUID は使いません。

zfs create -o mountpoint=/ \
    -o com.ubuntu.zsys:bootfs=yes \
    -o com.ubuntu.zsys:last-used=$(date +%s) rpool/ROOT/ubuntu
zfs create -o mountpoint=/boot bpool/BOOT/ubuntu
zfs create -o com.ubuntu.zsys:bootfs=no -o canmount=off rpool/ROOT/ubuntu/usr
zfs create -o com.ubuntu.zsys:bootfs=no -o canmount=off rpool/ROOT/ubuntu/var
zfs create rpool/ROOT/ubuntu/var/lib
zfs create rpool/ROOT/ubuntu/var/log
zfs create rpool/ROOT/ubuntu/var/spool
zfs create -o canmount=off -o mountpoint=/ rpool/USERDATA
zfs create -o com.ubuntu.zsys:bootfs-datasets=rpool/ROOT/ubuntu -o canmount=on -o mountpoint=/root rpool/USERDATA/root
chmod 700 /mnt/root

zfs create rpool/ROOT/ubuntu/var/lib/apt
zfs create rpool/ROOT/ubuntu/var/lib/dpkg
zfs create -o com.ubuntu.zsys:bootfs=no rpool/ROOT/ubuntu/srv
zfs create rpool/ROOT/ubuntu/var/lib/docker
zfs create rpool/ROOT/ubuntu/var/www
  • tmpfs をマウントします
mkdir /mnt/run
mount -t tmpfs tmpfs /mnt/run
mkdir /mnt/run/lock
  • debootstrap でパッケージをインストールします。少し時間がかかることを意識しておきます。
debootstrap noble /mnt

grub インストール前の rootfs 設定

  • grub インストールは chroot を伴いますので、その準備を行います。
    まずはキャッシュをコピーします。
mkdir /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/
  • HOSTNAME を入力しますが、自分の場合は ICHINO-PC としました。
hostname ICHINO-PC
hostname > /mnt/etc/hostname
  • 127.0.1.1 を /etc/hosts へ定義する。
    実は 127.0.1.1 の定義の必要性がわからず調べたところ Debian 系のディストリビューションの不具合回避のようです。とりあえず、参照先の通り /etc/hosts の最終行へ定義しました。
vi /mnt/etc/hosts
127.0.1.1 ICHINO-PC
  • network アドレス設定
    自宅のネットワークは dhcp で運用しているため、その内容にしました。
vi /mnt/etc/netplan/99_config.yaml
network:
  version: 2
  ethernets:
    enp4s0:
      dhcp4: true
  • apt で使用する source.list を設定しますが Ubuntu 24.04 から仕様が変わっていますのでそれに合わせた変更を行います。
cp /etc/apt/sources.list.d/ubuntu.sources /mnt/etc/apt/sources.list.d/
  • chroot します。DISK 変数は便利なので引き継ぎます。
mount --make-private --rbind /dev  /mnt/dev
mount --make-private --rbind /proc /mnt/proc
mount --make-private --rbind /sys  /mnt/sys

chroot /mnt /usr/bin/env DISK=$DISK bash --login
  • LOCALE や TIMEZONE を設定します。
apt update
locale-gen --purge en_US.UTF-8 ja_JP.UTF-8
apt install --yes vim

ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
dpkg-reconfigure -f noninteractive tzdata

grub インストール

  • 前準備
    いよいよ MBR へ grub をインストールしますが、その前に /etc/fstab 等を準備します。
apt install --yes dosfstools

mkdosfs -F 32 -s 1 -n EFI ${DISK}-part1
mkdir /boot/efi
echo /dev/disk/by-uuid/$(blkid -s UUID -o value ${DISK}-part1) \
    /boot/efi vfat defaults 0 0 >> /etc/fstab
mount /boot/efi
mkdir /boot/efi/grub /boot/grub
echo /boot/efi/grub /boot/grub none defaults,bind 0 0 >> /etc/fstab
mount /boot/grub
  • Legacy BIOS 用の grub をインストール
    このコマンドで Legacy BIOS 用のパッケージをインストールします。誤って UEFI のパッケージをインストールするとブートしなくなってしまいます。
apt install --yes grub-pc linux-image-generic zfs-initramfs zsys
  • os-prober の削除
    Windows などの複数OSの起動環境ではないため os-prober を削除します。
apt purge --yes os-prober
  • root passwd の設定
    自分で使う環境なので passwd も root としましたが、本来は難読化した文字列を推奨します。
passwd
  • swap 作成
mkswap -f ${DISK}-part2
echo /dev/disk/by-uuid/$(blkid -s UUID -o value ${DISK}-part2) \
    none swap discard 0 0 >> /etc/fstab
swapon -a
  • tmpfs を作成する
    本家サイトでは zpool で /tmp を作っていたらまずいので非推奨と書かれていましたが、その手順は実施していないので /tmp を作っておきます。
cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount
  • グループを追加します
addgroup --system lpadmin
addgroup --system lxd
addgroup --system sambashare
  • SSH を使えるようにします。
apt install --yes openssh-server
vi /etc/ssh/sshd_config

PermitRootLogin yes にしておきます。

  • initramfs を再生成します。
grub-probe /boot
update-initramfs -c -k all
  • /etc/default/grub を自分好みに編集します。
    一応本家サイトの内容も記載しておきます。
vi /etc/default/grub
# Comment out: GRUB_TIMEOUT_STYLE=hidden
# Set: GRUB_TIMEOUT=5
# Below GRUB_TIMEOUT, add: GRUB_RECORDFAIL_TIMEOUT=5
# Remove quiet and splash from: GRUB_CMDLINE_LINUX_DEFAULT
# Uncomment: GRUB_TERMINAL=console
# Save and quit.
  • grub の設定を更新します。
update-grub
  • grub インストールと grub-initrd-fallback.service を無効化します。
grub-install $DISK
systemctl mask grub-initrd-fallback.service
  • ZFSの準備を行います。
mkdir /etc/zfs/zfs-list.cache
touch /etc/zfs/zfs-list.cache/bpool
touch /etc/zfs/zfs-list.cache/rpool
zed -F &
  • ZFSの確認する。
    以下のコマンドとその実行内容を貼っておきます。
cat /etc/zfs/zfs-list.cache/bpool
cat /etc/zfs/zfs-list.cache/rpool
bpool	/boot	off	on	on	off	on	off	on	off	-	non-
bpool/BOOT	none	off	on	on	off	on	off	on	off	-	none	-	-	-	-	-	-	-	-
bpool/BOOT/ubuntu	/boot	on	on	on	off	on	off	on	offnone	-	-	-	-	-	-	-	-

rpool	/	off	on	on	on	on	off	on	off	-	non-
rpool/ROOT	none	off	on	on	on	on	off	on	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu	/	on	on	on	on	on	off	on	offnone	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/srv	/srv	on	on	on	on	on	off	on	offnone	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/usr	/usr	off	on	on	on	on	off	on	offnone	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var	/var	off	on	on	on	on	off	on	offnone	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/lib	/var/lib	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/lib/apt	/var/lib/apt	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/lib/docker	/var/lib/docker	on	on	on	on	on	off	on	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/lib/dpkg	/var/lib/dpkg	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/log	/var/log	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/spool	/var/spool	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/ROOT/ubuntu/var/www	/var/www	on	on	on	on	on	offon	off	-	none	-	-	-	-	-	-	-	-
rpool/USERDATA	/	off	on	on	on	on	off	on	off	-	none	-	-	-	-	-	-	-	-
rpool/USERDATA/ichino	/home/ichino	on	on	on	on	on	off	on	off	-	none	-	-	-	-	-	-	-	-
rpool/USERDATA/root	/root	on	on	on	on	on	off	on	offnone	-	-	-	-	-	-	-	-
  • zed を終了する。
fg
Press Ctrl-C.
  • cache のマウントポイントを修正
sed -Ei "s|/mnt/?|/|" /etc/zfs/zfs-list.cache/*
  • chroot 終了
exit
  • Live CD で以下を実行してマウントを解除します。
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \
    xargs -i{} umount -lf {}
zpool export -a
  • reboot して initramfs が起動するまで待ちます。
reboot
  • 初回だけ initramfs のコマンドプロンプトが表示されますので、以下のコマンドを実行すると起動します。
(initramfs) zpool import -f rpool
(initramfs) exit

一般ユーザの作成

username=ichino
zfs create -o com.ubuntu.zsys:bootfs-datasets=rpool/ROOT/ubuntu -o canmount=on -o mountpoint=/home/$username rpool/USERDATA/$username
adduser $username
cp -a /etc/skel/. /home/$username
chown -R $username:$username /home/$username
usermod -a -G adm,cdrom,dip,lpadmin,lxd,plugdev,sambashare,sudo $username

デスクトップ環境の構築

この手順は次の記事で記載します。