NetBSDの開発版(current)を使ってみる

[NetBSD Advent Calendar 2023](https://qiita.com/advent-calendar/2023/netbsd) 2日目の記事です。今日はNetBSDの開発版を使ってみる話をしようと思います。

## 開発版とは？

NetBSDに限らず、BSD系のOSでは次のリリースに向けて開発中のバージョンを"current"と読んでおり、"NetBSD-current"のように表記したりします。開発版ということもあり、次のリリースで提供される機能を先取りして試してみることができる反面、開発・テスト中のため、うまく動かない場合もあることを意識しておく必要もあります。

NetBSDの次のリリースはNetBSD-10が予定されており、現在のNetBSD-currentはNetBSD-10に向けた機能追加やバグ修正が行われています。

個人的にはNetBSDのリリース版を利用しているのですが、この機会なのでNetBSD-currentを試してみました。一度手順を把握するとあとは定期的にNetBSD-currentに更新するだけでよいので、その手順を本記事で紹介しようと思います。

## 開発版(NetBSD-current)をインストールする

 * [NetBSD-currentの追跡](http://www.jp.netbsd.org/ja/docs/current/)
 * [Information about NetBSD-current](https://www.netbsd.org/releases/current.html)
 * [Tracking NetBSD-current](https://www.netbsd.org/docs/current/)

さっそくNetBSD-currentをインストールしてみます。といっても毎回クリーンインストールするのではなく、インストール済のNetBSD環境にNetBSD-currentをインストールする形になります。

NetBSD-currentのインストール方法は以下のいずれかの手順で行います。

 * [NetBSD-currentのスナップショットを使う方法](http://www.jp.netbsd.org/ja/docs/current/#updating-from-snapshot)
 * [ソースツリーからインストール済のNetBSD環境を更新する](http://www.jp.netbsd.org/ja/docs/current/#updating)

### NetBSD-current配布物のダウンロード

今回は[NetBSD-currentのスナップショットを使う方法](http://www.jp.netbsd.org/ja/docs/current/#updating-from-snapshot)を試してみようと思います。NetBSD-currentの配布物は以下のURLで定期的に(2～3日くらい)最新のソースツリーからビルドされた成果物が配置されます。

 * [http://nyftp.netbsd.org/pub/NetBSD-daily/HEAD/](http://nyftp.netbsd.org/pub/NetBSD-daily/HEAD/)

現時点(12/2)では、今日ビルドされた成果物が最新のようです。

```sh
 $ w3m -dump http://nyftp.netbsd.org/pub/NetBSD-daily/HEAD/latest/amd64/binary/sets
Index of pub/NetBSD-daily/HEAD/202312011630Z/amd64/binary/sets/

          Name              Last modified       Size
Parent Directory          01-Dec-2023 19:07      1kB
MD5                       02-Dec-2023 01:16      2kB
SHA512                    02-Dec-2023 01:16      4kB
base.tar.xz               01-Dec-2023 19:29  48128kB
comp.tar.xz               01-Dec-2023 19:34  73486kB
debug.tar.xz              01-Dec-2023 20:01 344618kB
etc.tar.xz                01-Dec-2023 19:25    497kB
games.tar.xz              01-Dec-2023 19:25   2562kB
gpufw.tar.xz              01-Dec-2023 19:25   4047kB
kern-GENERIC.tar.xz       01-Dec-2023 19:23   8663kB
kern-GENERIC_KASLR.tar.xz 01-Dec-2023 19:23   8921kB
kern-XEN3_DOM0.tar.xz     01-Dec-2023 19:23   6469kB
kern-XEN3_DOMU.tar.xz     01-Dec-2023 19:23   2461kB
man.tar.xz                01-Dec-2023 19:26   7665kB
misc.tar.xz               01-Dec-2023 19:25   4054kB
modules.tar.xz            01-Dec-2023 19:25   9630kB
rescue.tar.xz             01-Dec-2023 19:25   3346kB
tests.tar.xz              01-Dec-2023 19:26  15013kB
text.tar.xz               01-Dec-2023 19:25   1890kB
xbase.tar.xz              01-Dec-2023 19:25   6334kB
xcomp.tar.xz              01-Dec-2023 19:26   5773kB
xdebug.tar.xz             01-Dec-2023 19:32  76257kB
xetc.tar.xz               01-Dec-2023 19:25     31kB
xfont.tar.xz              01-Dec-2023 19:26  28319kB
xserver.tar.xz            01-Dec-2023 19:27  26175kB
```

インストール済みのNetBSDの構成にもよりますが、必ずしも上記の配布物すべてが必要な訳ではなく、私の環境では以下の配布物をダウンロードしました。

 * `kern-GENERIC.tar.xz`
 * `base.tar.xz`
 * `comp.tar.xz`
 * `etc.tar.xz`
 * `man.tar.xz`
 * `modules.tar.xz`
 * `misc.tar.xz`
 * `MD5`

このダウンロードした配布物を展開し、NetBSD-currentをインストールして行きます。

### NetBSD-current配布物のインストール

まずはカーネルをインストールします。手順的にはカーネルだけNetBSD-currentに置き換えてから一度再起動します。これは新しいバイナリでは新しいシステムコールが追加されている場合があり、一緒にユーザランドを更新してしまうと稼働中のカーネルでは利用できないシステムコールを含んだコマンドが存在している状態になってしまうことがあるためです。

```sh
# # NetBSD-currentの配布物をダウンロードしたディレクトリ。
# cd 02-Dec-2023_0114/
#
# ls -lh
total 149M
-rw-r--r--  1 root  wheel  1.2K Dec  2 18:02 MD5
-rw-r--r--  1 root  wheel   47M Dec  2 17:59 base.tar.xz
-rw-r--r--  1 root  wheel   72M Dec  2 18:01 comp.tar.xz
-rw-r--r--  1 root  wheel  496K Dec  2 18:01 etc.tar.xz
-rw-r--r--  1 root  wheel  8.5M Dec  2 17:58 kern-GENERIC.tar.xz
-rw-r--r--  1 root  wheel  7.5M Dec  2 18:01 man.tar.xz
-rw-r--r--  1 root  wheel  4.0M Dec  2 18:02 misc.tar.xz
-rw-r--r--  1 root  wheel  9.4M Dec  2 18:02 modules.tar.xz
```

#### カーネルのインストール

`kern-GENERIC.tar.xz` を展開してインストール(実際にはファイルの置き換え)を行います。

```sh
# tar Jxvf kern-GENERIC.tar.xz
x ./netbsd
#
# ls -lh netbsd
-rwxr-xr-x  1 root  wheel   28M Dec  1 21:07 netbsd
#
# # 現在のカーネルをバックアップしておく。
# ln -fh /netbsd /netbsd.old
#
# # カーネルをNetBSD-currentのものに置き換える。
# # cp ./netbsd /netbsd
#
# # いったん再起動する。
# shutdown -r now
```

これでカーネルのインストールは完了です。

#### ユーザランドのインストール

NetBSDが無事に再起動してきたら、次はユーザランドのインストールです。こちらも配布物を展開するだけなので特段難しいことはありませんが、一点だけ注意があり、ファイルの展開時に `-p` オプション(許可属性の保持)を忘れずに指定するようにしてください。

```sh
# # カーネルはNetBSD-10.99.10になっている。
# uname -a
NetBSD nbsdcurrent 10.99.10 NetBSD 10.99.10 (GENERIC) #0: Fri Dec  1 12:07:19 UTC 2023  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64
#
# cd 02-Dec-2023_0114
# ls -lh
total 177M
-rw-r--r--  1 root  wheel  1.2K Dec  2 18:02 MD5
-rw-r--r--  1 root  wheel   47M Dec  2 17:59 base.tar.xz
-rw-r--r--  1 root  wheel   72M Dec  2 18:01 comp.tar.xz
-rw-r--r--  1 root  wheel  496K Dec  2 18:01 etc.tar.xz
-rw-r--r--  1 root  wheel  8.5M Dec  2 17:58 kern-GENERIC.tar.xz
-rw-r--r--  1 root  wheel  7.5M Dec  2 18:01 man.tar.xz
-rw-r--r--  1 root  wheel  4.0M Dec  2 18:02 misc.tar.xz
-rw-r--r--  1 root  wheel  9.4M Dec  2 18:02 modules.tar.xz
-rwxr-xr-x  1 root  wheel   28M Dec  1 21:07 netbsd
#
# # 配布物をroot(/)に展開する。
for i in base.tar.xz comp.tar.xz man.tar.xz misc.tar.xz modules.tar.xz
do
    tar Jxvfp $i -C /
done
```

これでユーザランドのインストールも完了しました。

#### /etcの更新

最後に `/etc` の更新です(これがNetBSD-currentのインストールでの難所かも…)。基本的には自動的に `/etc` の内容を更新できますが、どうしても手動で内容確認と修正・更新を行う場面が出てしまいます。

```sh
# # 配布物のetc.tar.gzに対し、/etcの更新コマンドを実行します。
# ls -lh etc.tar.xz
-rw-r--r--  1 root  wheel  496K Dec  2 18:01 etc.tar.xz
#
# # /etcの内容チェック。
# /usr/sbin/postinstall -s ./etc.tar.xz check
#
# # /etcの内容の自動修正(ただし自動修正できるもののみ)。
# /usr/sbin/postinstall -s ./etc.tar.xz fix
#
# # /etcの更新
# /usr/sbin/etcupdate -s ./etc.tar.xz
```

`etcupdate` を実行すると `/etc` の更新が行われ、その過程で自動修正できなかったファイル(差分があるもの)が表示されます。例えば以下のような感じです。

```sh
--- /.profile   2023-11-02 16:01:11.819013310 +0900
+++ /tmp/temproot/.profile      2023-12-01 21:07:19.000000000 +0900
@@ -25,6 +25,3 @@
 if [ -z "$SU_FROM" ] && [ "$PPID" -ne 1 ]; then
         echo "We recommend that you create a non-root account and use su(1) for root access."
 fi
-
-[ -f $HOME/.bashrc ] && source $HOME/.bashrc
-
--More--(END)
```

個人的にシェルを `bash` に切り替えており、 `.bashrc` を `.profile` から読み込む設定を追加していたため、上記の差分が出ています。

差分のあるファイルについては、どのように対応するかの選択肢が表示されます。

```sh
File: /.profile (modified)

Please select one of the following operations:

  d  Don't install the new file (keep your old file)
  i  Install the new file (overwrites your local modifications!)
  m  Merge the currently installed and new files
  s  Show the differences between the currently installed and new files
  su  Show differences in unified format ("diff -u")
  sc  Show differences in context format ("diff -c")
  ss  Show differences side by side ("sdiff -w80")
  scommand Show differences using the specified diff-like command
  v  Show the new file

What do you want to do? [Leave it for later]
```

基本的には以下のいずれかを選択します。

```
  d  Don't install the new file (keep your old file)
    →現在のファイルのままにする

  i  Install the new file (overwrites your local modifications!)
    →新しいファイルで上書きする(またはマージ後のファイルで上書きする)

  m  Merge the currently installed and new files
    →現在のファイルと新しいファイルをマージする
```

ここでは"m  Merge the currently installed and new files"を選択して手動でファイルをマージしてみます。"m"と入力すると、差分のある個所ごとにどうするかを聞かれます。個人的には"eb:     edit both diffs concatenated"を選択して新旧の差分から必要なものを選択するマージ方法が楽かと思います。

```sh
What do you want to do? [Leave it for later] m
                                       <
[ -f $HOME/.bashrc ] && source $HOME/. <
                                       <
%
e:      edit blank diff
eb:     edit both diffs concatenated
el:     edit left diff
er:     edit right diff
l:      choose left diff
r:      choose right diff
s:      silent mode--don't print identical lines
v:      verbose mode--print identical lines
q:      quit
%
```

"eb"を入力すると新旧の差分が表示されます。このケースでは、新しい方の差分が存在しないため、古いファイルの追加内容のみが表示されています。

```sh

[ -f $HOME/.bashrc ] && source $HOME/.bashrc

```

この例では追加内容を保持しておきたいため、このままファイルを保存し、変更内容をマージします。

ファイルの差分各々ついて確認が完了すると元の画面に戻ります。あとは"i  Install the merged file (overwrites your old file)"を選択して(マージ済の)ファイルで上書きします。

```sh
File: /.profile (modified)

Please select one of the following operations:

  d  Don't install the merged file (keep your old file)
  i  Install the merged file (overwrites your old file)
  m  Merge again (your old file against the result from the previous merge)
  s  Show the differences between the currently installed and new merged files
  su  Show differences in unified format ("diff -u")
  sc  Show differences in context format ("diff -c")
  ss  Show differences side by side ("sdiff -w80")
  scommand Show differences using the specified diff-like command
  u  Undo merge (start again with the original version of the new file)
  v  Show the merged file

What do you want to do? [Leave it for later] i
```

あとは差分のあるファイルについて、同様の確認が行われるので順次対応するだけです。
(「対応するだけです」とは言いますが、実際差分のあるファイルの数は結構あるので、この `/etc` の更新作業はちょっと大変です…)

```
--- /etc/dhcpcd.conf    2023-11-13 14:32:54.573070040 +0900
+++ /tmp/temproot/etc/dhcpcd.conf       2023-12-01 21:07:19.000000000 +0900
@@ -5,7 +5,7 @@
 #controlgroup wheel

 # Inform the DHCP server of our hostname for DDNS.
-hostname
+#hostname

 # Use the hardware address of the interface for the Client ID.
 #clientid
@@ -18,16 +18,12 @@
 # Persist interface configuration when dhcpcd exits.
 persistent

-# Rapid commit support.
-# Safe to enable by default because it requires the equivalent option set
-# on the server to actually work.
 # vendorclassid is set to blank to avoid sending the default of
 # dhcpcd-<version>:<os>:<machine>:<platform>
 vendorclassid
-option rapid_commit

--More--(byte 688)
```

##### /etcの更新で注意が必要な個所

先述した手順で `/etc` の更新は行えますが、 `passwd.conf` の更新については注意が必要です。
差分を見るとパスワードの暗号化方式が `sha1` から[argon2id](https://ja.wikipedia.org/wiki/Argon2)に変わっています。よりセキュアなハッシュではありますが、新しい方の差分でファイルを上書きしてしまうとログインできなくなってしまいます。
(おそらくパスワードのハッシュも何らかの方法で更新する必要がありますが、今のところ手順を調べきれていません…)

```sh
--- /etc/passwd.conf    2022-08-05 00:30:37.000000000 +0900
+++ /tmp/temproot/etc/passwd.conf       2023-12-01 21:07:19.000000000 +0900
@@ -1,9 +1,9 @@
-#      $NetBSD: passwd.conf,v 1.3 2010/12/03 21:40:04 jmmv Exp $
+#      $NetBSD: passwd.conf,v 1.4 2021/10/26 20:44:45 nia Exp $
 #
 # passwd.conf(5) -
 #      password configuration file
 #

 default:
-       localcipher = sha1
+       localcipher = argon2id
        ypcipher = old
--More--(END)
```

#### /etc更新後の再起動

`/etc` 更新後に再起動してNetBSD-currentのインストールは完了です。

```sh
What do you want to do? [Leave it for later] d

*** No changes were needed

Remove /tmp/temproot? (y/[n])
...
postinstall checks failed:
*** All done
#
# # 最後に再起動してNetBSD-currentのインストールは完了。
# shutdown -r now
...
# # 再起動後に確認。
# uname -a
NetBSD nbsd93 10.99.10 NetBSD 10.99.10 (GENERIC) #0: Tue Nov 14 03:03:18 UTC 2023  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64
```

## まとめ

NetBSD-currentのインストール手順を紹介しました。基本的には配布物を展開し、 `/etc` を更新するという手順になっています。今回はすべて手動で作業しましたが、配布物のダウンロードや展開の部分はスクリプト等で行うようにするとより気軽にNetBSD-currentへの更新が行えるかと思います。