openSUSE Leap Root on ZFSに書いてある手順をそのまま実行しても環境構築できない不幸の回避方法

# 事の起こり
[昔](https://qiita.com/toriiken1/items/2d92940c910d8a3ecb87)と違い、[Getting Started](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html)も充実してきて色々なディストリビューションのRoot on ZFSがありますが、なぜかUEFI bootingにしか対応していないディストリビューションが多いです。

|OS|UEFI boot|legacy (BIOS) boot|
|------------|:------------:|:------------:|
|Alpine Linux|対応|非対応|
|Arch Linux|対応|非対応|
|Debian|対応|対応|
|Fedora|対応|非対応|
|NixOS|対応|非対応|
|openSUSE|対応|対応|
|Rocky Linux|対応|非対応|
|Ubuntu|対応|対応|

本当はMBRにインストールしたいのですがGPTだらけです。仕方がないので、まずは前哨戦としてlegacy (BIOS) bootingで環境構築して、それを踏まえてMBRへのインストールは自力で何とかすることにします。何事も予行練習は大事です。

なお、上の表で分かるとおり、legacy (BIOS) bootingに対応しているのはDebinaとUbuntu、それにopenSUSEしかありません。まあ、Red HatがCentOSを切り捨てた時点で移行先を探して、結局ほかのRHEL互換OSを選択することに一抹の不安があったので思いきって見切りをつけてopenSUSEに乗り換えたので個人的には問題なしです。最近になってRHELのソースコード非公開とかやり始めて、乗り換えて正解だったと思うことしきり(笑)。できればSUSEには、RHEL互換OS騒動に首を突っ込む余裕があるならopenSUSEの痒いところに手が届かない残念なところを改善することに注力してほしいのですが。
# 不幸のはじまり
そんなこんなで、[openSUSE Leap Root on ZFS](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html)を見ながらRoot on ZFS環境を構築してみた訳ですが、記述どおりに実行していっても構築出来ません！ 基本的な流れは合っているけど、細かいところが適当すぎて、間違った記述が大量にあります。これ絶対検証してません(断言)。
という訳で、ここでは記述どおりに実行していった際に遭遇する不幸と、その対策を実行順に説明していこうと思います。まあ、備忘録ですね。
「ごたくはいいからさっさと正しい手順を出せー」というカルシウム足りてない人は、ページ最後の[正誤表](#不幸の回避方法という名の正誤表)まで飛んでください。
また、実行順に説明するため、説明に沿って環境構築していくと何度か最初からやり直すことになるので、このページを読みながら環境構築しても一発では完了しません。不幸を追体験したい人以外は、やはりページ最後の[正誤表](#不幸の回避方法という名の正誤表)を見ながら環境構築することをお勧めします。
ちなみに、実行環境はVirtualBoxで、LiveイメージはopenSUSE-Leap-15.5-Rescue-CD-x86_64-Build12.1-Media.isoを使用しています。

それでは、数々の不幸を順番に見ていきましょう。
## 一周目
### 不幸その1
最初の不幸は、[Step 5: System Configuration](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-5-system-configuration)の4. Configure a basic system environment:です。
```terminal
localhost:/ # ln -s /proc/self/mounts /etc/mtab
ln: failed to create symbolic link '/etc/mtab': File exists
```
これはエラーメッセージのまんまで/etc/mtabが存在しており、しかも/proc/self/mountsにシンボリックリンクが張られているので無視して構いません。というか、実行する必要がありません。

### 不幸その2
次なる不幸は、同じく[Step 5](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-5-system-configuration)の5. Optional: Reinstallation for stability:です。
```terminal
localhost:/ # zypper install -f permissions-config iputils ca-certificates&nbsp; ca-certificates-mozilla pam shadow dbus libutempter0 suse-module-tools util-linux
Loading repository data...
Reading installed packages...
Package 'permissions-config' not found.
Forcing installation of 'shadow-4.8.1-150400.10.12.1.x86_64' from repository 'Update repository with updates from SUSE Linux Enterprise 15'.
Forcing installation of 'util-linux-2.37.4-150500.7.16.x86_64' from repository 'oss'.
Forcing installation of 'pam-1.3.0-150000.6.61.1.x86_64' from repository 'oss'.
Forcing installation of 'ca-certificates-2+git20210309.21162a6-2.1.noarch' from repository 'oss'.
Forcing installation of 'ca-certificates-mozilla-2.62-150200.30.1.noarch' from repository 'Update repository with updates from SUSE Linux Enterprise 15'.
Forcing installation of 'suse-module-tools-15.5.3-150500.3.6.1.x86_64' from repository 'Update repository with updates from SUSE Linux Enterprise 15'.
Forcing installation of 'iputils-20221126-150500.1.1.x86_64' from repository 'oss'.
Forcing installation of 'libutempter0-1.1.6-3.42.x86_64' from repository 'oss'.
'dbus' not found in package names. Trying capabilities.
No provider of 'dbus' found.
Resolving package dependencies...

The following 3 packages are going to be upgraded:
  ca-certificates-mozilla shadow suse-module-tools

The following 4 packages are going to be reinstalled:
  ca-certificates libutempter0 pam util-linux

The following NEW package is going to be installed:
  iputils

3 packages to upgrade, 1 new, 4 to reinstall.
Overall download size: 2.9 MiB. Already cached: 0 B. After the operation,
additional 465.3 KiB will be used.
Continue? [y/n/v/...? shows all options] (y):
```
パッケージ名間違えているわ再インストールと言いつつ新規インストールしようとするわで酷い有り様です。
とりあえず、存在するそれっぽいパッケージ名を指定すれば再インストールは可能です。
```bash:場当たり的対応法
zypper install -f permissions iputils ca-certificates  ca-certificates-mozilla pam shadow dbus-1 libutempter0 suse-module-tools util-linux
```
もっとも、ドキュメントで<q>Some packages may have minor errors</q>とあるそもそもの原因は以下の2点だと思われます。
1. 最初に追加するリポジトリが不足している
1. パッケージのインストール時にファイルの競合チェックをしていない

ですので、正しい対応は以下のようになります。

1. [Step 4](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#id11)の1. Add repositories into chrooting directory:でsle-updateリポジトリを追加する
    ```bash
    zypper --root /mnt ar http://download.opensuse.org/update/leap/$(lsb_release -rs)/sle repo-sle-update
    ```
    ちなみに、この対応を行うと4. Install openSUSE zypper package system into chroot:は不要になります。
1. 同じく[Step 4](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#id11)の3. Install openSUSE Leap with zypper:および5. Recommended: Install openSUSE yast2 system into chroot:で`--download-in-advance`を追加する
    ```bash
    zypper --root /mnt install --download-in-advance -t pattern base(もしくはenhanced_base)
    zypper --root /mnt install --download-in-advance yast2
    zypper --root /mnt install --download-in-advance -t pattern yast2_basis
    ```
    なお、`--download-in-advance`を追加すると、baseパターンのインストール時にgzipの代わりにbusybox-gzipがインストールされる事があります(条件はさっぱり不明)。その場合、yast2_basisパターンのインストール時に競合が発生します。
    ```terminal
    localhost:~ # zypper --root /mnt install -t pattern yast2_basis
    Loading repository data...
    Reading installed packages...
    Resolving package dependencies...
    
    Problem: the to be installed pattern:yast2_basis-20220411-lp155.2.4.x86_64 requires 'patterns-yast-yast2_basis', but this requirement cannot be provided
      not installable providers: patterns-yast-yast2_basis-20220411-lp155.2.4.x86_64[oss]
     Solution 1: deinstallation of busybox-gzip-1.35.0-150400.4.5.1.noarch
     Solution 2: do not install pattern:yast2_basis-20220411-lp155.2.4.x86_64
     Solution 3: break pattern:yast2_basis-20220411-lp155.2.4.x86_64 by ignoring some of its dependencies
    
    Choose from above solutions by number or cancel [1/2/3/c/d/?] (c):
    ```
    ですので、この状態になったら1を選択します。
    バッチ的に処理したければ、以下の手順でもOKです。
    1. baseパターンのインストール後にbusybox-gzipをremoveする
    1. yast2のインストール時にgzipもインストールする

なお、これは致命的な不幸ではない(そもそもOptionalだし)ので、このまま続行します。どうせこの後に嫌でも周回プレイすることになるので、まずは行けるところまで行きます。

### 不幸その3
[Step 5](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-5-system-configuration)の11. Install GRUBも同じ不幸です。
```terminal
localhost:/ # zypper install grub2-x86_64-pc
Loading repository data...
Reading installed packages...
Package 'grub2-x86_64-pc' not found.
Resolving package dependencies...
Nothing to do.
```
`zypper search grub2`を実行してみれば分かりますが、UEFI用のgrub2は確かにx86_64(grub2-x86_64-efi)ですが、legacy (BIOS)用のgrub2はi386(grub2-i386-pc)です。
なんでこうもパッケージ名を間違えられるのか不思議で仕方無いですが、それはともかく`zypper install grub2-i386-pc`するのが正解、と思ったら実は大間違い。でも現時点では間違いに気付くのは困難(エラー出ないし)なので、ここではgrub2-i386-pcをインストールして先に進みます。
### 不幸その4
[Step 5](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-5-system-configuration)の14. Enable importing bpoolですが、[Step 4](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#id11)の3. Install openSUSE Leap with zypper:でbaseパターンをインストールした場合は以下の不幸が見付かります。
```terminal
localhost:/ # vi /etc/systemd/system/zfs-import-bpool.service
bash: vi: command not found
```
これは簡単。`zypper install -y vim`するだけです。
### 不幸その5
[Step 6: Kernel Installation](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-6-kernel-installation)の4. Refresh the initrd files:です。
```terminal
localhost:/ # mkinitrd
bash: mkinitrd: command not found
```
これも`zypper install -y dracut-mkinitrd-deprecated`するだけです。
### 不幸その6
[Step 7: Grub2 Installation](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-7-grub2-installation)がlegacy (BIOS) bootingにおける最大の鬼門です。
この辺りから、不幸レベルが上昇してきます。

まず、5. Check that /boot/grub2/grub.cfg have the menuentry root=ZFS=rpool/ROOT/suse, like this:ですが、そもそも/boot/grub2/grub.cfgが存在しません。
```terminal
localhost:/ # ls /boot/grub2/
themes
```
これ、エラーメッセージは何も出ていませんが、直前の`update-bootloader`が失敗してます。正確にはブートローダーの種類を指定しない為に処理をスキップしているので、`echo LOADER_TYPE="grub2" > /etc/sysconfig/bootloader`を実行してから`update-bootloader`を実行します。
これで/boot/grub2/grub.cfgが生成されます。
```terminal
localhost:/ # ls /boot/grub2/
grub.cfg  grubenv  themes
```
ところが、いざ/boot/grub2/grub.cfgを確認してみると、root=が正しく設定されていません。
```terminal
localhost:/ # grep -m1 linux.*root= /boot/grub2/grub.cfg
        linux   /BOOT/suse@/vmlinuz-5.14.21-150500.55.31-default root=ZFS=/ROOT/suse
```
ここで「その後に書いてある通りに、/etc/default/grubに設定追加すればいいじゃん」と思ったそこのアナタ、大甘です。山葉堂の新メニューのワッフルより甘いです(黙れ)。たしかにこの通りに設定して`update-bootloader`を実行すれば、以下のように一応正しいroot=は設定されます。(間違った設定も残ったままだけど、とりあえずそれは置いておく)
```terminal:何の解決にもならない対処法
localhost:/ # echo 'GRUB_CMDLINE_LINUX="root=ZFS=rpool/ROOT/suse"' >> /etc/default/grub
localhost:/ # update-bootloader
localhost:/ # grep -m1 linux.*root= /boot/grub2/grub.cfg
        linux   /BOOT/suse@/vmlinuz-5.14.21-150500.55.31-default root=ZFS=/ROOT/suse root=ZFS=rpool/ROOT/suse
```
でも、この後の6. Install the boot loader:が同じ理由で失敗するので、ここでの対処は不要(というか無駄)です。
### 不幸その7
という訳で、やってきました回避不能の不幸其の壱。
```terminal
localhost:/ # grub2-install $DISK
Installing for i386-pc platform.
grub2-install: error: ../grub-core/kern/fs.c:121:unknown filesystem.
```
「Step 7の最初に`grub2-probe /boot`で正しくzfsを認識してるの確認してるのに何で？」と思うかもしれませんが、/bootだけ認識できても駄目なのです。legacy (BIOS) booting環境では、/もzfsとして認識できないと`grub2-install`は成功しません。
```terminal
localhost:/ # grub2-probe /
grub2-probe: error: ../grub-core/kern/fs.c:121:unknown filesystem.
```
なので、/をgrub2に正しく認識させる必要があるのですが、もう詰んでます。どうにもなりません。

この原因は、[Step 2: Disk Formatting](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-2-disk-formatting)の5. Create the root pool:でrpoolを作成する際にdnodesizeプロパティを変更したためです。なので、rpool作成時に`-O dnodesize=auto`を指定してはいけません。ダメ。ゼッタイ。
また、zfs-2.2.0から追加された以下のfeatureは自動的にactiveになってしまうので、明示的にdisabledにする必要があります。
+ head_errlog
+ vdev_zaps_v2

という訳で、最初からやり直しです。二週目の開始〜。

ちなみに、周回プレイ(笑)する時は、Live CDの再起動からやり直す必要があります。
「chrootからexitしてから[Step 3: System Installation](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-3-system-installation)のmount解除してzpoolをexportすれば、[Step 2: Disk Formatting](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-2-disk-formatting)の5. Create the root pool:から再開できるんじゃ？」と思った聡い人は、実際試してみてください。理屈の上では正しいのですが、少なくと私の環境では駄目でした。(この件に関しては後にも出てきます)
## 二周目
### 不幸その8
今まで説明した不幸を全て回避しながら進めば[Step 7: Grub2 Installation](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-7-grub2-installation)の6. Install the boot loader:までは問題なく進むと思ったらぎっちょんちょん、[Step 2: Disk Formatting](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-2-disk-formatting)の4. Create the boot pool:にて一週目には出現しなかった不幸が出現します。
```terminal
localhost:~ # zpool create \
>     -o cachefile=/etc/zfs/zpool.cache \
>     -o ashift=12 -d \
>     -o feature@async_destroy=enabled \
>     -o feature@bookmarks=enabled \
>     -o feature@embedded_data=enabled \
>     -o feature@empty_bpobj=enabled \
>     -o feature@enabled_txg=enabled \
>     -o feature@extensible_dataset=enabled \
>     -o feature@filesystem_limits=enabled \
>     -o feature@hole_birth=enabled \
>     -o feature@large_blocks=enabled \
>     -o feature@lz4_compress=enabled \
>     -o feature@spacemap_histogram=enabled \
>     -o feature@zpool_checkpoint=enabled \
>     -O acltype=posixacl -O canmount=off -O compression=lz4 \
>     -O devices=off -O normalization=formD -O relatime=on -O xattr=sa \
>     -O mountpoint=/boot -R /mnt \
>     bpool ${DISK}-part3
invalid vdev specification
use '-f' to override the following errors:
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB0167fad0-f4c6ae75-part3 is part of exported pool 'bpool'
```
まあ、エラーメッセージに従って`-f`を指定すれば済む話ではありますが。ちなみに、ある意味当然ですが、この後のrpool作成も同様の対応が必要です。

これでようやく[不幸その7](#不幸その7)まで戻ってこられます。
一周目と違って正しい設定がされているか確認してみます。念の為、grub2が/を認識できるかも確認します。
```terminal
localhost:/ # grub2-probe /
zfs
localhost:/ # grep -m1 linux.*root= /boot/grub2/grub.cfg
        linux   /BOOT/suse@/vmlinuz-5.14.21-150500.55.31-default root=ZFS=rpool/ROOT/suse
```
### 不幸その9
なので、安心して`grub2-install`を実行すると、一週目から変態した不幸が。
```terminal
localhost:/ # grub2-install $DISK
Installing for i386-pc platform.
grub2-install: error: cannot open `/usr/share/grub2/i386-pc/zfs.mod': No such file or directory.
```
[不幸その2](#不幸その2)の回避策でgrub2-i386-pcをインストールしましたが、grubがzfsにアクセスするために必要なzfs.modはgrub2-i386-pcに含まれておらず、実はgrub2-i386-pc-extrasに含まれているので、本当はgrub2-i386-pc-extrasをインストールするのが正しいです。

なお、grub2が/を認識できるようになったので、[Step 8: Systemd-Boot Installation](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-8-systemd-boot-installation)は不要です。そもそもこれ、どう見てもUEFI booting用なんだけど……。
### 不幸その10
[Step 9: Filesystem Configuration](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-9-filesystem-configuration)の1. Fix filesystem mount ordering:で見たことのある不幸に再会です。
```terminal
localhost:/ # ln -s /usr/lib/zfs/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
ln: failed to create symbolic link '/etc/zfs/zed.d/history_event-zfs-list-cacher.sh': File exists
```
[不幸その1](#不幸その1)と同じなので、これも無視です。
### 不幸その11
[Step 10: First Boot](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-10-first-boot)の4. Run these commands in the LiveCD environment to unmount all filesystems:、やってきました回避不能の不幸其の弍。
```terminal
localhost:~ # zpool export -a
cannot export 'rpool': pool is busy
```
/proc/mountsを確認すると/mnt配下は全てアンマウントしてあるのに、なぜかexportできません。bpoolはexportできてるのに……。

「もうこの後はrebootするだけだし、別にいいんじゃね？」と思うかもしれませんが、さにあらず、baseパターンをインストールした場合、ここでexportできないと再起動した際にzpoolのimportに失敗してemergency modeに入ってしまいます。(enhanced_baseパターンイストール時にimportに失敗しない理由はさっぱり不明)
本当にexportできれば正常にimport出来るのかは確認したことがない(なにせexport出来ないんだから)のですが、実際にimport出来ないのは事実なので何とかします。
とりあえず手っ取り早いのは、emergency modeで強制的にimportしてexportすることです。
```console
:/root# zpool import -f rpool
:/root# zpool export rpool
:/root# reboot
```
これで正常にimportできるようになり、無事起動するようになります。

ちなみに、そもそもimportに失敗せずemergency modeに入らないようにする対応方法もあります。
という訳で、確認のために三週目いってみよ〜。興味の無い人は次の不幸までスキップしてOKです。
## 三周目
まず、[Step 2](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-2-disk-formatting)の5. Create the root pool:の前に[Step 5](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-5-system-configuration)の10. Recommended: Generate and setup hostid:を実行します。
そして、[Step 4](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-4-install-system)の3. Install openSUSE Leap with zypper:の後に`cp /etc/hostid /mnt/etc/`を実行します。
これで[Step 10](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-10-first-boot)の5. Reboot:で`reboot`を実行すると、起動時にrpoolも正常にimportされるようになります。

一応、ここまででRoot on ZFSに起因する不幸は全て解消しました。なので、これ以降の不幸はZFSとは関係ない内容とその対処になります。……正直、この時点でもう自分としてはやりきった感があるので、これ以降の説明は適当です(笑)。
### 不幸その12
そんな訳で、ここから環境構築の第二部を始めたいところですが、この時点で一つ大きな不幸が行く手を阻んでいます。
それは、<strong>ネットワーク設定してないから適当なターミナルソフトからssh接続してコマンドのコピペが出来ない！</strong>
コンソールからログインしてコマンドをちまちま手打ちしなきゃいけないとか、何の嫌がらせですか？
という訳で、まずネットワーク設定です。ちなみにDHCP設定だけです。固定IP環境の人は自力でガンガレ。
```bash
cat > /etc/sysconfig/network/ifcfg-eth0 <<EOF
BOOTPROTO=dhcp
STARTMODE=hotplug
EOF
systemctl restart wicked
```
ちなみに、真っ当な方法はYaSTでのネットワーク設定ですが、YaSTの画面キャプチャーをペタペタ貼るのは面倒臭い(ｦｲｦｲ)なので、手順だけ列挙しておきます。こちらもDHCP設定だけです。固定(以下略)。
<dl>
<dt>[YaST Control Center]</dt>
<dd>Systemを選択→Enter→Network Settingsを選択→Enter</dt>
<dt>[Network Settings]</dt>
<dd>F4キー押下(Edit)</dd>
<dt>[Network Card Setup]</dt>
<dd>TABキー2回押下で、Dynamic Addressを選択→スペースキー押下→F10キー押下(Next)</dd>
<dt>[Network Settings]</dt>
<dd>F10キー押下(OK)</dd>
<dt>[YaST Control Center]</dt>
<dd>F9キー押下(Quit)</dd>
</dl>

ネットワーク設定が終わったら`systemctl enable --now sshd`を実行します。本来ならインストール時に有効化しておくべきなのに、インストールだけして放置って何がしたいのやら。
sshdを起動したらログアウトします。すると、再起動直後は何も表示されていなかったeth0にIPアドレスが設定されている筈です。う〜ん、openSUSEはこれが便利。
### 不幸その13
ようやく環境構築が再開できると思ったら、しょっぱなの[Step 10: First Boot](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-10-first-boot)の6. Create a user account:で不幸の三連撃です。
(面倒臭いの(ｦｲ)で、usernameのまま実行しています)
```terminal
HOSTNAME:~ # adduser username
-bash: adduser: command not found
```
openSUSEにadduserなんてコマンドは無いYO! あるのはuseraddだYO!
しかし、useraddでも何やらエラーが出ます。
```terminal:中途半端な対処法
HOSTNAME:~ # useradd username
Group 'mail' not found. Creating the user mailbox file with 0600 mode.
HOSTNAME:~ # grep mail /etc/group
HOSTNAME:~ # ls -l /var/spool/mail/
total 1
-rw------- 1 username users 0 Nov  4 14:58 username
```
たしかにmailグループは存在しないようです(useradd(1)のバグ？)。system-groupパッケージを検索してもmailグループが含まれていそうなパッケージは見当たらないし、とりあえずメールボックスは作成されているので気にしないことにします。
### 不幸その14
そして次なる不幸が。
```terminal
HOSTNAME:~ # chown -R username:username /home/username
chown: invalid group: 'username:username'
HOSTNAME:~ # grep username /etc/group
HOSTNAME:~ #
```
たしかにusernameグループは存在しないようです(dejavu)。
理由は、openSUSEのuseradd(1)は、-Uオプションを指定しないとユーザー名と同名のグループは作成しないからです。
なので、-Uを指定してユーザーアカウントを作り直したい訳ですが、既に存在するユーザーアカウントを上書きすることは出来ないので、一旦削除してからやり直します。
```terminal
HOSTNAME:~ # userdel -r username
userdel: /home/username not owned by username, not removing
HOSTNAME:~ # useradd -U username
Group 'mail' not found. Creating the user mailbox file with 0600 mode.
HOSTNAME:~ # grep username /etc/group
username:!:1000:
HOSTNAME:~ #
```
userdel(1)のエラーも無視します。たとえ/home/usernameのオーナーがusernameだったとしても、`zfs create`で作成したdatasetなのでuserdel(1)で削除するのは不可能だし。
### 不幸その15
そして、最後のコマンドでも不幸が。
```terminal
HOSTNAME:~ # usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video username
usermod: group 'dip' does not exist
usermod: group 'floppy' does not exist
usermod: group 'netdev' does not exist
usermod: group 'plugdev' does not exist
usermod: group 'sudo' does not exist
HOSTNAME:~ # grep -e dip -e floppy -e netdev -e plugdev -e sudo /etc/group
HOSTNAME:~ #
```
たしかに(以下略)。存在しないグループは無視して存在するグループにだけ設定するような気の利いた挙動はしてくれないので、正しく`usermod -a -G audio,cdrom,video username`と指定する必要があります。
それにしても、なんでこんなエラー出まくるのかというと、実はここの内容は[DebianのStep 6: First Boot](https://openzfs.github.io/openzfs-docs/Getting%20Started/Debian/Debian%20Bullseye%20Root%20on%20ZFS.html#step-6-first-boot)の6. Create a user account:の劣化コピペなので、全然openSUSE用になってないからです。&#x2588;&#x2588;なの？ &#x2588;ぬの？(検閲済)
### 不幸その16
[Step 10](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-10-first-boot)の7. Mirror GRUBは複数ディスクにインストールした場合に必要らしいので今回はスキップしますが、まあ書いてある内容は酷いの一言です。
efibootmgr(1)はインストールされていないわインストールして実行してみたらlegacy_bootなんてメッセージは出ないわgrub-installなんてコマンドopenSUSEには無いわ(またDebianか!?)$DISKなんて設定していない環境変数指定してるわ最後の説明文は意味不明だわ(やっぱりDebianか!?)、6. Create a user account:と合わせて、よくもまあこんな適当な内容を書けるもんだと、感心することしきりです。
という訳で、対処方法はありません(強いて言えば無視するのが対処方法)が、不幸として記録しておきます。
### 不幸(?)その17
[Step 11: Optional: Configure Swap](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-11-optional-configure-swap)の1. Create a volume dataset (zvol) for use as a swap device:では、以下のWarningが出ます。環境によっては16384ではなく8192と出力される場合もあります。
```terminal
Warning: volblocksize (4096) is less than the default minimum block size (16384).
To reduce wasted space a volblocksize of 16384 is recommended.
```
普通に考えたらページサイズ単位でスワップする筈なので、ブロックサイズはページサイズに合わせておいた方が良さそうな気もするけど、zfsのvolblocksizeをデフォルトより小さくするのって、実際どうなんでしょうね？
まあ、今時はzram使うのが普通(?)だから、そもそもスワップデバイス作る必要無いかも(Optionalだし)。
### 不幸その18
同じく[Step 11](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-11-optional-configure-swap)の2. Configure the swap device:では、以下の不幸が発生します。
```terminal
HOSTNAME:~ # echo RESUME=none > /etc/initramfs-tools/conf.d/resume
-bash: /etc/initramfs-tools/conf.d/resume: No such file or directory
```
とりあえず、ディレクトリを作成すればエラーは出なくなるけど、こんな存在しないディレクトリ配下のファイルを誰が参照するの？ 無駄じゃね？ という訳で無視します。
### 不幸その19
最後のStepです(長かった……)。[Step 12: Final Cleanup](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-12-final-cleanup)の最初にこう書いてあります。
>Login using the account you created.

[Step 10](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-10-first-boot)の6. Create a user account:で確かにアカウント作成した(エラー出まくりだったけどな！)けど、パスワード設定してないからログイン出来ねーよ！
ついでに言えば、
>Ensure the system (including networking) works normally.

とも書いてあるけど、ネットワーク設定の話もどこにも書いてないけどな！ 暗黙の設定を前提にするのは止めてもらえませんかね？

という訳で、rootでパスワードを設定します。
```terminal
HOSTNAME:~ # passwd username
New password: (雑なパスワードを入力)
BAD PASSWORD: it is based on a dictionary word
BAD PASSWORD: is too simple
Retype new password: (雑なパスワードを入力)
passwd: password updated successfully
```
cracklibがインストールしてあるので、雑なパスワードを設定しようとすると怒られますが、rootで実行しているので華麗にスルーです(笑)。
ちゃんとした環境で運用する場合は、初回ログイン時にパスワードを再設定するように仕込んで、雑なパスワードでは利用できないようにしましょう。
### 不幸その20
ここから一般ユーザーでの操作になりますが、しょっぱなから不幸に見舞われます……前途多難だ。
```terminal
username@HOSTNAME:~> sudo zfs destroy bpool/BOOT/suse@install
-bash: sudo: command not found
```
[Step 4. Install System](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-4-install-system)の3. Install openSUSE Leap with zypper:でbaseパターンを選んでいるとsudoはインストールされません。なので、これまたrootで`zypper install -y sudo`を実行します。
### 不幸その21
これ以降、運がいい(悪い?)と何の不幸にも見舞われず、最後まで進むかもしれませんが、[Step 12: Final Cleanup](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-12-final-cleanup)の3. Optional: Disable the root password:を実行した人は最後のブービートラップにハメられました。ご愁傷様です(-人-)。

rootのパスワードを削除しても、しばらく(5分?)はキャッシュが残っているのでsudoを実行してもパスワードを訊かれないため気が付かない(私だけ?)のですが、時間が経ってから実行するとsudo出来なくなります。
```terminal
username@HOSTNAME:~> sudo vi /etc/default/grub
[sudo] password for root:
Sorry, try again.
[sudo] password for root:
Sorry, try again.
[sudo] password for root:
sudo: 3 incorrect password attempts
```
openSUSE Leap使いには常識(他のディストリからしたら非常識かも)ですが、一般ユーザーのsudoにはrootのパスワードが要求されます。それなのにOptionalとはいえrootのパスワードを無効化するとか、もうね、アボカド。バナナかと。(権力による改竄)
openSUSE LeapのGetting Started書いた奴、絶対にopenSUSE Leap使ったこと無いだろ……。
という訳で、3. Optional: Disable the root password:は実行してはいけません。ダメ。ゼッタイ。(2回目)

なお「openSUSE使ってるなら何も考えずにrootのパスワード無効化してるんじゃねーよ。自業自得だろ」というツッコミは禁止です。正論だからって何言ってもいい訳じゃねーぞ(逆ギレ)。

この時点で、コンソールなりターミナルソフトからのrootログインが残っていれば、そこからrootのパスワードを設定し直すことで復活することが出来ますが、残ってなかったら……最後の最後になって周回を重ねましょうか(滅)。まあ、最初から全部環境構築し直さなくても復活させる方法は幾つかあるので、致命的な不幸という訳でもありません。疲れたから説明はしないけど。もう、ゴールしていいよね(だから黙れ)。
それにしても、直下にTroubleshootingで[Rescuing using a Live CD](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#rescuing-using-a-live-cd)が書かれているのは、親切なんだかマッチポンプなんだかよく分からん(笑)。
### 不幸その22
ゴールできなかった(笑)。
[Step 12](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-12-final-cleanup)の5. Optional: Re-enable the graphical boot process:で、既に[Step 7](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html#step-7-grub2-installation)の4. Update the boot configuration:で回避した不幸が再び襲ってきます。
```terminal
username@HOSTNAME:~> sudo update-bootloader
update-bootloader: 2023-12-01 23:13:38 <3> update-bootloader-8837 run_command.336: '/usr/lib/bootloader/grub2/config' failed with exit code 1, output:
<<<<<<<<<<<<<<<<
+ /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg
/usr/sbin/grub2-probe: error: failed to get canonical path of `/dev/ata-VBOX_HARDDISK_VB0167fad0-f4c6ae75-part4'.
>>>>>>>>>>>>>>>>
```
rootで実行すると問題ないのに一般ユーザーがsudo経由で実行するとエラーになるのは、環境変数ZPOOL_VDEV_NAME_PATHが未設定になってしまうからです。
なので、sudo実行時に環境変数を引き継ぐように`sudo sh -c "echo Defaults env_keep += ZPOOL_VDEV_NAME_PATH > /etc/sudoers.d/grub"`を実行します。
## 始まりの終わり
最後まで気の抜けないドキュメントですが、何とか[openSUSE Leap Root on ZFS](https://openzfs.github.io/openzfs-docs/Getting%20Started/openSUSE/openSUSE%20Leap%20Root%20on%20ZFS.html)を元にlegacy (BIOS) bootingでの環境構築が出来ました。
この次は今回の成果を踏まえて、GPTでなくMBRでインストールする手順について書く予定です。(本当に書きたいのはさらにその次の内容なんだけど)
# 不幸の回避方法(という名の正誤表)
<table>
<caption><em>Step 2: Disk Formatting</em></caption>
<!-- 不幸その6 回避策 -->
<!-- 不幸その7 回避策 -->
<!-- 不幸その11 回避策 -->
<tr><th colspan="2" style="text-align: center">5. Create the root pool:</th></tr>
<tr><th>誤</th><td>
zpool create \<br>
&nbsp; &nbsp; -o cachefile=/etc/zfs/zpool.cache \<br>
&nbsp; &nbsp; -o ashift=12 \<br>
&nbsp; &nbsp; -O acltype=posixacl -O canmount=off -O compression=lz4 \<br>
&nbsp; &nbsp; -O dnodesize=auto -O normalization=formD -O relatime=on \ <br>
&nbsp; &nbsp; -O xattr=sa -O mountpoint=/ -R /mnt \<br>
&nbsp; &nbsp; rpool ${DISK}-part4
</td></tr>
<tr><th>正</th><td>
cd /root<br>
zypper install wget<br>
wget https://github.com/openzfs/zfs/files/4537537/genhostid.sh.gz<br>
gzip -d genhostid.sh.gz<br>
chmod +x genhostid.sh<br>
zgenhostid `/root/genhostid.sh`<br>
zpool create \<br>
&nbsp; &nbsp; -o cachefile=/etc/zfs/zpool.cache \<br>
&nbsp; &nbsp; -o ashift=12 \<br>
&nbsp; &nbsp; -o feature@head_errlog=disabled \<br>
&nbsp; &nbsp; -o feature@vdev_zaps_v2=disabled \<br>
&nbsp; &nbsp; -O acltype=posixacl -O canmount=off -O compression=lz4 \<br>
&nbsp; &nbsp; -O normalization=formD -O relatime=on \<br>
&nbsp; &nbsp; -O xattr=sa -O mountpoint=/ -R /mnt \<br>
&nbsp; &nbsp; rpool ${DISK}-part4
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 4. Install System</em></caption>
<!-- 不幸その2 回避策 -->
<tr><th colspan="2" style="text-align: center">1. Add repositories into chrooting directory:</th></tr>
<tr><th>誤</th><td>
-
</td></tr>
<tr><th>正</th><td>
最後に以下のコマンドを実行<br>
zypper --root /mnt ar http://download.opensuse.org/update/leap/$(lsb_release -rs)/sle repo-sle-update<br>
</td></tr>
<!-- 不幸その2 回避策 -->
<!-- 不幸その4 回避策 -->
<!-- 不幸その5 回避策 -->
<!-- 不幸その11 回避策 -->
<!-- 不幸その20 回避策 -->
<tr><th colspan="2" style="text-align: center">
3. Install openSUSE Leap with zypper:<br>
a. Install base packages of openSUSE Leap with zypper (Recommended for server):
</th></tr>
<tr><th>誤</th><td>
zypper --root /mnt install -t pattern base
</td></tr>
<tr><th>正</th><td>
zypper --root /mnt install -y --download-in-advance -t pattern base<br>
zypper --root /mnt install -y --download-in-advance vim dracut-mkinitrd-deprecated sudo<br>
cp /etc/hostid /mnt/etc/<br>
※busybox-gzipがインストールされた場合<br>
zypper --root /mnt install --download-in-advance gzip → 1(deinstallation of busybox-gzip)を選択<br>
</td></tr>
<!-- 不幸その2 回避策 -->
<!-- 不幸その11 回避策 -->
<tr><th colspan="2" style="text-align: center">
3. Install openSUSE Leap with zypper:<br>
b. Install enhanced base of openSUSE Leap with zypper (Recommended for desktop):
</th></tr>
<tr><th>誤</th><td>
zypper --root /mnt install -t pattern enhanced_base
</td></tr>
<tr><th>正</th><td>
zypper --root /mnt install -y --download-in-advance -t pattern enhanced_base<br>
cp /etc/hostid /mnt/etc/
</td></tr>
<!-- 不幸その2 回避策 -->
<tr><th colspan="2" style="text-align: center">4. Install openSUSE zypper package system into chroot:</th></tr>
<tr><th>誤</th><td>
zypper --root /mnt install zypper
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
<!-- 不幸その2 回避策 -->
<tr><th colspan="2" style="text-align: center">
5. Recommended: Install openSUSE yast2 system into chroot:<br>
(baseパターンインストール時のみ実行)<br>
</th></tr>
<tr><th>誤</th><td>
zypper --root /mnt install yast2<br>
zypper --root /mnt install -t pattern yast2_basis<br>
</td></tr>
<tr><th>正</th><td>
zypper --root /mnt install -y --download-in-advance yast2<br>
zypper --root /mnt install -y --download-in-advance -t pattern yast2_basis<br>
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 5: System Configuration</em></caption>
<!-- 不幸その1 回避策 -->
<tr><th colspan="2" style="text-align: center">4. Configure a basic system environment:</th></tr>
<tr><th>誤</th><td>
ln -s /proc/self/mounts /etc/mtab
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
<!-- 不幸その2 回避策 -->
<tr><th colspan="2" style="text-align: center">5. Optional: Reinstallation for stability:</th></tr>
<tr><th>誤</th><td>
zypper install -f permissions-config iputils ca-certificates  ca-certificates-mozilla pam shadow dbus libutempter0 suse-module-tools util-linux
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
<!-- 不幸その11 回避策 -->
<tr><th colspan="2" style="text-align: center">10. Recommended: Generate and setup hostid:</th></tr>
<tr><th>誤</th><td>
cd /root<br>
zypper install wget<br>
wget https://github.com/openzfs/zfs/files/4537537/genhostid.sh.gz<br>
gzip -d genhostid.sh.gz<br>
chmod +x genhostid.sh<br>
zgenhostid `/root/genhostid.sh`
</td></tr>
<tr><th>正</th><td>
実行しない(Step 2で実行済)
</td></tr>
<!-- 不幸その3 回避策 -->
<!-- 不幸その9 回避策 -->
<tr><th colspan="2" style="text-align: center">11. Install GRUB</th></tr>
<tr><th>誤</th><td>
zypper install grub2-x86_64-pc
</td></tr>
<tr><th>正</th><td>
zypper install -y grub2-i386-pc-extras
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 7: Grub2 Installation</em></caption>
<!-- 不幸その6 回避策 -->
<tr><th colspan="2" style="text-align: center">4. Update the boot configuration:</th></tr>
<tr><th>誤</th><td>
update-bootloader
</td></tr>
<tr><th>正</th><td>
echo LOADER_TYPE="grub2" &gt; /etc/sysconfig/bootloader<br>
update-bootloader
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 9: Filesystem Configuration</em></caption>
<!-- 不幸その10 回避策 -->
<tr><th colspan="2" style="text-align: center">1. Filesystem Configuration</th></tr>
<tr><th>誤</th><td>
ln -s /usr/lib/zfs/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 10: First Boot</em></caption>
<!-- 不幸その12 回避策 -->
<tr><th colspan="2" style="text-align: center">1. Optional: Install SSH:</th></tr>
<tr><th>誤</th><td>
zypper install -y openssh-server
</td></tr>
<tr><th>正</th><td>
zypper install -y openssh-server<br>
systemctl enable sshd<br>
cat &gt; /etc/sysconfig/network/ifcfg-eth0 &lt;&lt;EOF<br>
BOOTPROTO=dhcp<br>
STARTMODE=hotplug<br>
EOF<br>
</td></tr>
<!-- 不幸その11 回避策 -->
<tr><th colspan="2" style="text-align: center">4. Run these commands in the LiveCD environment to unmount all filesystems:</th></tr>
<tr><th>誤</th><td>
zpool export -a
</td></tr>
<tr><th>正</th><td>
エラーを無視
</td></tr>
<!-- 不幸その13 回避策 -->
<!-- 不幸その14 回避策 -->
<!-- 不幸その19 回避策 -->
<tr><th colspan="2" style="text-align: center">6. Create a user account:</th></tr>
<tr><th>誤</th><td>
adduser username
</td></tr>
<tr><th>正</th><td>
useradd -U username<br>
passwd username
</td></tr>
<!-- 不幸その15 回避策 -->
<tr><th colspan="2" style="text-align: center">6. Create a user account:</th></tr>
<tr><th>誤</th><td>
usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video username
</td></tr>
<tr><th>正</th><td>
usermod -a -G audio,cdrom,video username
</td></tr>
<!-- 不幸その16 回避策 -->
<tr><th colspan="2" style="text-align: center">7. Mirror GRUB</th></tr>
<tr><th>誤</th><td>
efibootmgr -v<br>
grub-install $DISK
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 11: Optional: Configure Swap</em></caption>
<!-- 不幸その18 回避策 -->
<tr><th colspan="2" style="text-align: center">
2. Configure the swap device:
</th></tr>
<tr><th>誤</th><td>
echo RESUME=none &gt; /etc/initramfs-tools/conf.d/resume
</td></tr>
<tr><th>正</th><td>
実行しない<br>
※ファイルを作成したい場合は、以下を実行する<br>
mkdir -p /etc/initramfs-tools/conf.d<br>
echo RESUME=none &gt; /etc/initramfs-tools/conf.d/resume
</td></tr>
</table>
<!---------------------------------------------------------------->
<br clear="left">
<table>
<caption><em>Step 12: Final Cleanup</em></caption>
<!-- 不幸その21 回避策 -->
<tr><th colspan="2" style="text-align: center">3. Optional: Disable the root password:</th></tr>
<tr><th>誤</th><td>
sudo usermod -p '*' root
</td></tr>
<tr><th>正</th><td>
実行しない
</td></tr>
<!-- 不幸その22 回避策 -->
<tr><th colspan="2" style="text-align: center">5. Optional: Re-enable the graphical boot process:</th></tr>
<tr><th>誤</th><td>
sudo update-bootloader
</td></tr>
<tr><th>正</th><td>
sudo sh -c "echo Defaults env_keep += ZPOOL_VDEV_NAME_PATH > /etc/sudoers.d/grub"<br>
sudo update-bootloader
</td></tr>
</table>