• 作成:

GentooInstallBattle on ThinkPad P16s Gen 2 AMD

楽天リーベイツのLenovoの還元日に備えた新しいラップトップPCを買うための検討メモ - ncaq で書いた通り、 ThinkPad P16s Gen 2 AMD を購入しました。

SSDをThinkPad P16s Gen 2 AMDのSSDの換装が非常に簡単でした - ncaqに書いた通り換装し終えたので、 Gentoo Linuxをインストールしていきます。

参考リンク

インストールメディア

今回は最初からGentooの公式インストールメディアを適当にUSBメモリにddして起動することにしました。

セキュアブートを無効化

セキュアブートを一度無効化します。頑張れば有効なままLinuxをインストールすることも出来ますが面倒な割にメリットを感じられません。

セキュアブート自体も現実の攻撃はランサムウェアとかバックドア設置とか、既にブートしているOSへの攻撃の報告ばかり聞くので、あんまり効果を感じないんですよね。

基本的に市販のPCはセキュアブート有効になってるから攻撃者側も狙わないだけで、実は防ぐことに成功しているのかもしれませんが。

TPM関連の機能は面白そうですが。

GNU/Linux的にもBitLockerと同じような運用方法は考えられます。 luksに2つのキーを設置して、回復キー相当の長くてセキュアですが毎回入力することは耐えられないパスワードをバックアップ用に用意してどこかにメモしておきます。そしてTPMでブート関連の設定変更が行われてないことが分かった時のみ毎回入力も容易なパスワードで解除できるようにします。これなら攻撃された時に容易なパスワードで解除できないので、変更に心当たりが無ければ警戒出来ますし、 GRUBの再インストールなど心当たりがあれば長いパスワードで回復できますね。

両方要求するような設定は出来るのだろうかと思いましたが、少なくともsystemdの設定には--tpm2-with-pinとして存在するみたいですね。 systemd - LUKS + TPM2 + PIN - Unix & Linux Stack Exchange

でもTPMから無条件で値を読み取れるかどうかを判断するという話はセキュアブートでブートローダを縛るのと関係あるんでしょうか。例えばBitLockerをPINだけで解除できるか回復キーが必要かどうかの判定はセキュアブート無効でも動いていますし。

それにさっき書いたようにセキュアブートは既に起動しているOSへの攻撃にはほぼ無力です。私が一番懸念している紛失・盗難にあったPCからデータを抜きされるケースも、 TPMチェックに引っかからないようにUSBキーボードを装って入力を試みれば良いはずなので、セキュアブートはほぼ無力なはずです。間違ってないよね?

なので素直にYubico YubiKey Bio Fido Editionみたいな、指紋認証付きのキーで解錠した方が盗難対策には適していると感じています。キーを紛失したらメモっておいた回復キーを入力します。

ただこれ結構高いんですよね。二段階認証は唯一のキーを持ち運ばなくて良いTOTPの方が便利でAWSとかは何故かYubiKeyと併用出来ないので使う気にならないので、単純に指紋認証して固定パスワードを入力してくれるだけのもので十分なんですが。ただ安物は本当にセキュアなのか不安なので何を買えば良いのか分からない。

ともかく後でセキュアブートを有効化するかは置いておいて、 Gentooの公式インストールメディアは署名されていないようなので、一度セキュアブートを無効化してインストールします。

起動

F12で起動メニューを開けるらしいですが、数回失敗して成功しました。安定性がよく分からない。

まあ普段はWindows起動したくなってもGRUB経由で起動するので、問題にはなりませんが。

OpenSSHで操作

いつもの通り(いつからだ?)、家の中なので適当にパスワード設定してデスクトップPCからOpenSSHで操作します。

起動時にも出来ると促されます。

これでコピペ面倒くさい問題とかとは無縁ですし、既にセットアップ済みのデスクトップPCのEmacsからtrampで接続にも行けます。

ThinkPad P16s Gen 2には最初から有線LANポートがあるのでネットワーク接続が面倒くさい問題とは無縁ですね。いやまあUSBの有線LANアダプターを使えないケースとか殆ど無いですが。

パーティション

暗号化されていないbootパーティション

EFIパーティションはWindowsと不本意ですが共用しますが、 bootパーティションは必要です。

bootの場所から意味のある暗号化をするのはかなり面倒な割にメリットが少ないです。なので素直にLinuxカーネルなどの別に漏れても良いファイルはbootパーティションに置いてしまいます。

前回はbootパーティションはGRUBが絶対に理解できるようにext4にしましたが、今回はBtrfsに統一します。 GRUBも結構前のバージョンの2.04からzstd圧縮のBtrfsをサポートしているので、問題ないでしょう。なるべくシンプルに保ちたい。

後述しますがやめておいたほうが良いです。素直にext4などにしましょう。

bootパーティションのサイズは余裕を持って2GBぐらい確保しておきます。本当はこんなに要らないと思いますが、後から増やすのはLVMとか使わないと面倒くさいので。前回は1GBでしたけど特に問題なかったみたいですね。どうしても容量が足りなくなったら2GBを解決しても仕方ないので2TBのSSDを買ってきます。

swapパーティション

swapパーティションは別途作ることにします。 swapファイルは今のBtrfsなら普通にサポートしていますが、 CoWがちゃんと無効になってるかとかサブボリュームの外に置くとか面倒くさいので、あえて古臭い方法を取ります。

swapパーティションのサイズは、使うかどうかはともかくハイバネーションを考えて、メモリ容量は32GBなので少し多めの33GBを確保しておきます。

そんなに必要かどうかは全く分かりません。そもそも12スレッドしか無くて32GBメモリを積んでいるのでswapが本当に必要なのかも分かりません。一応ディスクキャッシュをどんどん積んでいって、プログラムの使わない部分は逆にswapに追いやることで高速に動作出来るとは思いますが、そもそもキャッシュ込みでも12スレッドで32GBメモリを自分の用途ではあまり使い切らないですね。

Gentooの文書では2倍が推奨されているので64GBにしようかと思いましたが、 2倍が推奨されるのは流石にメモリが少ない時代の名残りかなあという気がします。最近あまり信用してないけれどRHELもそう書いています。第15章 swap 領域 Red Hat Enterprise Linux 7 | Red Hat Customer Portal いやこれは基本的にサーバ向けの文書じゃないかというとそうなんですが。

swapが大きすぎるとさっさとOOM Killerが働いて欲しい無限ループプログラムを書いた時にディスクに延々と書き込み続けることがあります。その意味でもあまり過剰に確保はしたくありません。

また2GBレベルならともかく30GBの追加容量は空き容量が速度に関わるSSDで追加したくないですね。足りなくなったら2TBを買ってくれば良いというか、 SN850XじゃなくてSN770を買ってかなり後悔しているので買い換える口実が欲しいとかはあるんですが。

rootパーティション

前回は742GBのパーティションになりましたが、今回は660GBのパーティションに縮小してしまいましたね。

まあ前回もそれだけあってsnapshots取りまくっても余裕があったので、今回も余裕だと思います。

足りなくなるとしたらAI関連のモデル入れまくるとかでしょうけど、 NVIDIAのGPUどころかdGPU自体積んでないこのPCでやっても効率が悪すぎるので、多分やらないと思います。

暗号化パーティション

さて暗号化パーティションを生成しましょう。

まずcryptsetup benchmarkを実行してアルゴリズムの速度を調べてみます。

livecd ~ # cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1      2052007 iterations per second for 256-bit key
PBKDF2-sha256    3334104 iterations per second for 256-bit key
PBKDF2-sha512    1696724 iterations per second for 256-bit key
PBKDF2-ripemd160  783689 iterations per second for 256-bit key
PBKDF2-whirlpool  601247 iterations per second for 256-bit key
argon2i       8 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id      8 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
#     Algorithm |       Key |      Encryption |      Decryption
        aes-cbc        128b      1028.8 MiB/s      4541.7 MiB/s
    serpent-cbc        128b        97.5 MiB/s       720.4 MiB/s
    twofish-cbc        128b       192.8 MiB/s       438.0 MiB/s
        aes-cbc        256b       775.5 MiB/s      3640.0 MiB/s
    serpent-cbc        256b        99.2 MiB/s       720.6 MiB/s
    twofish-cbc        256b       195.0 MiB/s       436.5 MiB/s
        aes-xts        256b      3771.8 MiB/s      3799.7 MiB/s
    serpent-xts        256b       590.9 MiB/s       592.2 MiB/s
    twofish-xts        256b       379.8 MiB/s       387.0 MiB/s
        aes-xts        512b      3169.8 MiB/s      3175.5 MiB/s
    serpent-xts        512b       597.4 MiB/s       592.3 MiB/s
    twofish-xts        512b       381.0 MiB/s       384.8 MiB/s

という結果になりました。結局はデフォルトで指定されるaes-xts-plain64がバランス良くて良さそうですね。 Zen4で変わるかなと思ったんですが、特に変わらないようです。後でディスクIOも測ったりAVX-512を有効化出来たとしてもオーダーが違うレベルの速度差ですね。

作者たちが当然賢いということで今回は全部デフォルトオプションで良さそうです。

Btrfsのサブボリューム

前回と同じくBtrfsを使うんですが、前回と違う所はルートのサブボリュームを直接使わず、推奨ファイルシステムレイアウト - Snapper - ArchWiki に従ってある程度分離することにします。

前回は/usr/などはサブボリュームにしてスナップショットの範囲外にしていましたが、よく考えてみると/usr/local/とかはPortageの管理外にあるので、スナップショットの範囲内にしてディスクが足りなくなったら素直にスナップショットの量を減らした方が良いのではないかと考えました。 /usr/のロールバックが出来ればシステムの復元もかなり実用的ですね。

一度素でmountしてサブボリュームを作ってumountして今後は@をマウントポイントとして使用ですね。 @, @home, @snapshots, @var_logだけ作りました。他のスナップショットしなくて良いやつは他のサブボリュームの入れ子で作ってしまいます。入れ子にするとトラブル時に独立性を保つのが面倒になりそうですが、 cache系とかは最悪破壊されても問題が無いので。

stage3を解凍するより先にサブボリュームはmountしました。

merged-usr

少し嫌な予感がしてたんですが、 Downloads – Gentoo Linux でダウンロードできるデフォルトのsystemdのstage3はmerged-usrではなかったんですね。 Gentooでsystemdを使ってる人はさっさとUsrMoveしないといけないよという話

流石にsystemd公式サポート外の環境で動かすつもりもなく、後から移行すると面倒なので、最初からmerge-usrを使おうと思ってたんですが、デスクトッププロファイルをダウンロードしていたので、マージされていませんでした。

いくら選択とは言えデフォルトではそうなっていると思ってたんですが。

ディレクトリの変動よりはせいぜいUSEフラグの変化程度だろうデスクトッププロファイルから移行するほうがまだ楽そうなので、マージされたものを選択しておきます。

セットアップ前のhostnameの設定は無理そう

etc-portage などの展開でホスト名で分岐するようにしたので、 make.confなどの保存の前にホスト名を設定したいです。

livecdがsystemdで動いていない以上hostnamectlはまだ使えないため、 systemd-firstboot --prompt --setup-machine-idを実行してみます。

駄目です。再起動とかしないとコマンドには反映されないやつですね。おとなしくホスト名依存のビデオカードの設定とかは取り除いておきます。

一時的にリポジトリ設定をgitから変更

livecdにはgitが入っていないため、リポジトリ同期をgitにしているとgitのインストールすら出来ないし、 profileの設定も出来ません。

おとなしくrsyncのデフォルト値にしておきます。

gentoo-kernelを採用してみます

gentoo-kernelという名前で設定ファイルを読み込んで自動でコンパイルからインストールまでしてくれるパッケージが、新規にはもう推奨されるレベルに達したようですね。

Gitでカーネル設定を管理出来そうなので、こちらに移行するのも良さそうです。

細かく設定するにしてもむしろgentoo-kernelを前提に設定ファイルを組み立てていくほうがバージョン管理されて良さそうな気がします。

基本的にカーネルのサイズはさほど問題にしないので、デフォルトの値に有効にしたい機能を追加するという形で十分そうですね。

ついでにセキュアブートの対応もUSEフラグにあるので楽に出来るかもしれません。今のLTSバージョン6.1にはないみたいですが。 6.4からサポート開始するみたいですね。

新規にやることに新規にやることを重ねたくないので、やるならデスクトップ含めて全部移行かなあと思ったのですが、まっさらなシステムには最初から適応しておいた方が良さそうな気がするので、移行は最初は少し面倒かもしれませんがこれを使ってみます。

とりあえずはデフォルトの設定でインストールしてみて、カーネルの設定はまた今後やります。

例えば-march=nativeが効いてないっぽいことが気になりますね。 Linuxカーネル領域で自動AVXが欲しいことはほぼ無いとは思いますが、キャッシュのサイズ検知とかで最適化は出来るはず。再頒布容易に出来るようにデフォルトでは最適化しないのは当然な気もしますが。

暗号化ディスクの起動

暗号化ディスクを使っていてもちゃんと起動できるか不安ですが、やってみます。 /etc/crypttab書いてれば良いのかなあ。

/etc/conf.d/dmcryptはディレクトリから察せられるようにOpenRC向けで、 systemdブートには向いていないようなので、 crypttabに書きます。

最近はGentooでもsystemd-bootのサポート追加されてるんですね。 GRUBより高速なことが多いみたいです。ただ他のディストリビューションと違ってGentooの場合、 systemdが起動しなくてもOpenRCで起動できたりするので、 systemd絶対依存にするのは少し気が引けますね。暗号化initramfsとか少し面倒なものを取り扱うので、 GRUB継続ですね。

とりあえずGRUB_CMDLINE_LINUXrd.luks.uuid=暗号化されてopenの対象になるパーティションのUUIDを追加すると、起動はしました。

ただしエラーまみれでレスキューモードでの起動になってしまいました。

起動時にinitramfsがerror: sparse file not allowed.と表示してくる

Strange error at boot - Support - Manjaro Linux Forum によると、 GRUB_SAVEDEFAULT="true"しているのが悪いようです。

grub は btrfs に書き込めないため、これは /boot が btrfs でない場合にのみ機能します。ただし、"sparse file not allowed. Press any key to continue." という誤解を招くエラーメッセージが生成されます。

GRUB/ヒントとテクニック - ArchWiki

なるほどそうだったですね。

GRUB_SAVEDEFAULT=trueは使いたいので、ブートパーティションはやっぱりext4にしておいた方が無難な気がしてきましたね。今回の教訓としましょう。

systemd-cryptsetup: Failed to deactivate: Device or resource busyで殆どのディスクマウントに失敗する

ルートパーティション

rootがalready existsで失敗するのは/etc/crypttabを書いていたのが逆に良くないみたいですね。 rootは起動時に解読されてマウントされるので、その後またマウントしようとしてエラーになるようです。コメントアウトして問題では無くなったので、ファイルごと削除しました。

しかし/etc/crypttabを書いているガイドもそれなりにありますね。 GRUBのカーネルパラメータかcrypttabのどっちかだけで良いということでしょうか。内部でdracutを使っているのでdracutの設定ファイルとして書くのが正解?

TRIMを有効にするオプションはここに書いていたので、ブートオプションにも移植する必要がありそうですね。

rd.luks.options=discardで良さそう。 discardを逐一実行するのではなくTRIMを定期実行する場合でもこちらで良いのかな。

他のパーティション

間抜けなことに暗号化を解く前のUUIDを指定していました。解いた後を指定することで無事解決。

感想

単体で起動が出来てエラーも無くなったということで、インストールバトルとしてはここで終了で良いでしょう。

ThinkPad専用のファンコントロールツールとかあるみたいですが、それはまた今度試してみます。別に記事にはしないかも。

ThinkPadだからと言って何か苦労したことは殆どありませんでした。流石は公式でUbuntuやRHELとは言えLinuxを動作OSとして書いてあるだけのことはあります。

今回面倒だったのはgentoo-kernelを採用するか悩んだり、 initramfsの生成をそれに任せて、前のgenkernelでinitramfsを生成する方法と違う方法を使ったことにありますね。