Ubuntu 24.04をUSBメモリブートでAutoInstall

# はじめに

環境が壊れてクリーンインストールからやり直したい！ ということが良くあると思います。
OSインストールは簡単な作業ですが、入力項目がそこそこあり、しかも入力と入力の間にちょっと待ち時間があるのがプチストレスです。

そこで自動インストールに挑戦してみました。

自動インストールについて調べると、ISOファイルを作る方法（CD-Rに焼く必要がある）と、PXEブートする方法（ネットワークブート用のサーバを用意する必要がある）が見つかります。

私がやりたいのはUSBブートで、定義ファイルもUSBメモリに置きたいんですが、解説しているページを見つけることができませんでした。

やってみたら簡単にできたので紹介します。（たどり着くのは大変だったけど・・・）

Ubuntu 24.04 で試しましたが、AutoInstall が採用されたバージョンなら同様の手順で実現できると思います。

作業概要は下図の通りです。（手動インストールして定義ファイルを作るところは省略してます）

![スクリーンショット 2024-06-08 183748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104360/33a70a89-e16c-257d-53be-3d4f094f9ae8.png)


# Rufus でブータブルUSBメモリを作る

これを読んでいる方はご存じかと思いますが、ISOファイルからブータブルUSBメモリを作る [Rufus](https://rufus.ie/ja/) というツールがあります。

ご存じない方はおググりください。

手元で実行したときのスクショを貼っておきます。

![2024-05-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104360/518d5576-af5d-bdd6-5d59-d89f8f2db465.png)


# とりあえず手動でインストールする

「自動インストールの定義ファイルをどう作るか問題」なのですが、手動でインストールすると定義ファイルが生成されます。便利ですね。

Rufusで作成したUSBメモリを用い、お好みの設定で手動インストールしましょう。

ホスト名やユーザー名は、汎用っぽい名前でもいいし、定義ファイルを修正（検索）するときに便利なようにダサイローマ字名を付けるのもいいかもしれませんね。

# 定義ファイルを拾ってUSBメモリに反映

Ubuntu のインストールが終わったら、定義ファイルが `/var/log/installer/autoinstall-user-data` に出来上がります。これをローカルPCにコピーしましょう。

ちなみに最近のTeraTermではSCPが使えるのでそれを使うと便利かも。最近と言っても10年以上前ですが。（自分は最近知った）

Rufus で作ったUSBメモリに適当な名前（例えば `insco` ）のディレクトリを作り、拾ってきた `autoinstall-user-data` を `user-data` という名前にしてコピーします。

もう一つ、`meta-data` という名前の空ファイルも置きます。

定義ファイルは以上なのですが、インストール時に定義ファイルを読みこませる設定が必要です。

USBメモリの `/boot/grub/grub.cfg` をテキストエディタで開き
```
	linux	/casper/vmlinuz ---
```
の行を
```
	linux	/casper/vmlinuz autoinstall "ds=nocloud-net;s=file:///cdrom/insco/" ---
```
のように編集します。
（`autoinstall "ds=nocloud-net;s=file:///cdrom/insco/"` を追記です。）

ちなみに、ここの指定方法の調査に時間が掛かりました。USBメモリにCD-ROMのフリをさせるので、USBメモリのルートディレクトリが `/cdrom` にマウントされるんですね。

## この項まとめ

USBメモリを下記のようにいじる

`/insco/user-data` ← Ubuntuの `/var/log/installer/autoinstall-user-data` からコピー
`/insco/meta-data` ← 空ファイル
`/boot/grub/grub.cfg` ← 上記修正

# 自動インストールしてみる

これで自動インストールできるブータブルUSBメモリが出来上がりました。

再度ターゲットPCに挿してUSBブートすると、インストール後の再起動まで自動で進みます。

# もう一工夫

## GRUB選択待ち時間削減

USBブート直後の画面でインストールやメモリテストなどを選ぶところで30秒待たされます。

`grub.cfg` の 
```
set timeout=30
```
の30を小さな値にすることで待ち時間を短縮することができます。

ただ、設定用のWindowsマシンに挿したままうっかりUSBブートしてしまうとWindows環境が飛んでしまうので、その猶予時間として30秒は残しておいた方がいいかもしれません。

## パーティション設定

`autoinstall-user-data` に書かれたパーティション設定にはドライブのシリアル番号などが書かれており、別のドライブを装着したマシンだと `matched no disk` というエラーで止まってしまい、自動インストールできません。

ドライブに依存しない設定にするため、

`serial: ～`
`wwn: ～`

の行を削除しましょう。

`wwn: ` は無い場合もあります。

（SATA接続のSSDだけで調査したため、NVMe接続の場合はもしかしたら事情が異なるかもしれません）

また、パーティションサイズも手動インストール時の容量でガッツリ書かれてしまっています。

デフォルトでインストールすると、

| パーティション | サイズ | 用途 |
|:------------|:----------- |:------------|
| `/dev/sda1` | 1.1G        | `/boot/efi`   |
| `/dev/sda2` | 2G          | `/boot`       |
| `/dev/sda3` | 残り全部    | LVM物理ボリューム？|

となって、LVM物理ボリュームの半分（100GBを超えたら100GB）が `/` の論理ボリュームとして割り当てられるようです。

`sda3` の「残り全部」が今あるディスクに依存したサイズになっているので、`-1` にしてどんなサイズでも「残り全部」になるようにします。
また、`/` の論理ボリュームサイズも `-1` にして全部確保しちゃいましょう。

具体的には、下から `size:` を検索して引っかかる2か所の数字を `-1` にします。

offset（パーティション開始位置）が書いてあって心配になりますが、後ろをいじる分には offset は変わらないのでそのままで良いはずです。

（offset を削除すると自動計算してくれるようです。ただし、第一パーティションのoffsetは4Kアライメントを考慮した値が書いてありそうな気がするので、そこだけは削除しないほうがいいかもしれません）

## パーティション設定まとめ

`/insco/user-data` の

`serial: ～` ←行削除
`wwn: ～` ←行削除（もしあれば）
下から2番目の `size: nnn` ← -1 にする
下から1番目の `size: nnn` ← -1 にする


# Ubuntuインストール後にUSBブート

UEFI画面からブート順を設定してUSBブートを優先にしていても、Ubuntuのインストールが完了すると第一優先がUbuntuになってしまい、USBブートする際にUEFI画面を出さなければならなくなってプチ面倒です。

`efibootmgr` コマンドで現在の設定をみて、

`sudo efibootmgr -n 番号`

で次の1回だけ起動優先度を変えることができます。

なお、起動後に挿したUSBメモリは`efibootmgr`では見えないようなので、認識のための再起動を1回挟むことになります。それでも、キーボードを持ち替えてタイミングよく[F2]などを押す作業が無いのは気が楽です。

（こーゆーことができますよの紹介なので、あえて詳しく書いてないです。）
（UEFIブート事情はよく分からないので間違ったこと言ってるかも。）

# 研究課題

- パスワード設定

password: の行に指定する文字列は openssl passwd ナントカ で生成できるみたいです。

- SSH公開鍵認証設定

ちゃんとやらないと怒られるかも。
ローカル環境なので許して。

- apt ミラーサイトの固定

近くのミラーサイトを探索するフェーズがあるのですが、手動インストール時の探索結果は `autoinstall-user-data` に反映されていないようです。近いサイトに固定する方法があるような気がしています。

- シリアルコンソール

grub.cfg の記述でシリアルコンソールを有効にできるらしいです。