Ubuntu 22.04をAutoInstallでインストールしてみた (UEFI&MBR両対応)

# はじめに 

:::note info
24.04でのAutoInstallについては [Ubuntu 24.04でのAutoInstallについて](https://qiita.com/YasuhiroABE/items/db3339ee057447431bbc) にまとめています。
:::

OSの自動インストールは複数台のシステムを均一な構成に(Kitting)するためには、かなり便利な仕組みで広く提供されています。同時にまったく標準化されていない分野でもあり、メーカーやシステム毎に異なる仕組みが提供されています。

Ubuntuでは自動化の仕組みとしてDebian由来のPreseedが長く利用可能でしたが、20.04からAutoInstallのみの提供となりました。

22.04からは、Live Server ISOイメージそのものの構成も少し変更され、カスタマイズしたISOイメージの作成は少し難易度が高いようにも感じられます。

Ubuntuは広く普及していますので、検索すれば様々な方法・ユーティリティに関する情報が入手できます。ここでは基本的なコマンドやツールを中心に、オリジナルを大きく変更せずに利用する方法を模索していきます。

なお、まだUEFIに対応していない古いIAシステムを利用していますので、isolinuxから起動させる手順についても含めています。

# 参考資料

* https://ubuntu.com/server/docs/install/autoinstall
公式のAutoInstallマニュアル
* https://askubuntu.com/questions/1403546/ubuntu-22-04-build-iso-both-mbr-and-efi
公式ISOイメージを作成した時の、xorrisoのコマンドラインが転載されています。
* https://curtin.readthedocs.io/en/latest/topics/storage.html
user-dataに記載するstorage関連の設定についての詳細

## 成果物

GitHubにファイル一式と作業手順をまとめたMakefileを含めていますので、こちらを利用してください。
ISOファイルを作成するだけであれば、README.mdファイルを読むだけですぐに始められるはずです。

* https://github.com/YasuhiroABE/ub2204-autoinstall-iso

以下ではこの作業をまとめるまでの経緯について説明しています。

# 環境

## 作業環境

作業自体は20.04以降のLTS環境でも可能です。

* Ubuntu 20.04 LTS amd64 Server版
* Ubuntu 22.04 LTS amd64 Server版

22.04ではfdiskのバージョンが上がって、fdisk -lコマンドの出力が言語環境によって変化するので、env LANG=C を付けるなど言語環境に依存しないよう注意が必要です。

## インストール対象

Ubuntu Server ISOイメージを主に利用しています。Desktop版のイメージはflavourによって利用しているフレームワークが違いますが、基本的には今回の方法では動作しないはずです。

以下のようなシステムで利用しています。

* PC Engines APU1/APU2 (coreboot v4.16.0.3, ``make gen-isolinux``を利用)
* 仮想マシン (BIOS/UEFI 両モードでの検証) (VMware Workstation 17 Pro)
* Fujitsu RX100 S7 (``make gen-isolinux``を利用)
* Fujitsu TX120 S3p (同上)
* ThinkPad x220/x230/x270/T430/T430s
* Protectli VP2420 (coreboot v4.19)
* Beelink EQ12
* Minisforum UM480XT

22.04のISOイメージを利用した場合には、再起動後に再びインストーラーが起動する現象を確認しています。これを防ぐために最新のGitHubに登録しているプロジェクトに含まれるuser-data.efiファイルでは、``shutdown: poweroff`` を指定しています。

> 以前「ループが発生する場合には、late_commandsに``shutdown -h now``を指定することでシステムを停止するといった対策があります。」と記載していましたが、これは適切な方法ではありませんでした。

> 2023年08年04日以前のGitHubに登録しているプロジェクトファイルでは、grub.cfgで``console=ttyS0,115200n8``を常に指定していました。私が使用していたシステムでは問題なく動作していましたが、これが原因でインストール後に適切に動作しないシステムが確認できたため修正しています。

# スクリプト

プロジェクトはGitHubで公開しています。

* https://github.com/YasuhiroABE/ub2204-autoinstall-iso

Makefileを配置しているので、次のような手順で作業を始められます。

詳細はREADME.mdを確認してください。

## 利用方法

```bash:ISOイメージの作成方法
$ git clone https://github.com/YasuhiroABE/ub2204-autoinstall-iso.git
$ cd ub2204-autoinstall-iso
$ make download
$ make init

# 環境に合わせて config/user-data 等を変更

$ make setup
$ env LANG=C make geniso
## カレントディレクトリに ubuntu-custom-autoinstaller.$(shell date +%Y%m%d.%H%M%S).iso ファイルが作成される

## user-data ファイル等の編集と、ISOファイルの生成、検証作業の以降繰り返し
```

この中で実行している``make download`` では、ISOイメージをダウンロードします。古いファイルにアクセスするとエラーになるので、Makefileの先頭にある``ISO_FILENAME`` 行が最新のISOイメージファイル名になるよう、必要に応じて修正してください。

既にISOファイルをダウンロードしている場合には、シンボリックリンク・ファイルなどで配置することができますが、ファイル名がこのMakefileの先頭にある``ISO_FILENAME``のファイル名と一致するようにMakefileを確認・修正してください。

# 20.04と比較したISOイメージ、AutoInstall関連の変更点

20.04で動作していたスクリプト群の22.04への対応作業をして気になった点は以下のとおりです。

* EFI領域のイメージ(efi.img)がISOファイルに含まれなくなった。このため既存のISOファイルからEFI領域を指定してxorrisoに渡す必要がある。
* isolinux関連のファイルがISOファイルに含まれなくなった。このためisolinux.binの代りに boot/grub/i386-pc/eltorito.img が準備されていて、MBR(BIOS)環境からgrub.cfgを読んで起動します。
  * ブートセクタに配置する isohdpfx.bin に相当するファイルも含まれないため、既存のISOファイルから該当領域を指定してxorrisoに渡しています。

一部でファイルとしては提供されなくなったコードを利用するために、公式のISOイメージから該当領域をコピーする必要があります。xorrisoに必要な情報を渡すための処理がMakefileに含まれています。

従来のISOファイルで利用されていたisolinuxを利用する方法は、grub/grub.cfgとisolinux/txt.cfgの両方をメンテナンスしなければいけないため嫌われたのかもしれません。

22.04からはUEFIとMBRの両方がgrubを利用するようになっています。AutoInstallの利用者としてはkernelに渡す起動オプションが一箇所に記述できるので、この点はメリットですが、EFIのためにESP領域を確保するなど扱いに違いがあるので、user-dataファイルをUEFとMBRで共用することはできません。結局、大きな変更の割にはユーザー側のメリットは少なそうです。

個人的によく使っているPC Engines社製のAPU/APU2の起動にはisolinuxが必要だったので、isolinux.binやisohdpfx.bin等のファイルを配置するタスクもMakefileには含まれています。詳細はREADMEを参照してください。

## efi.img がISOイメージに含まれなくなった点への対応

従来は次のようなコマンドラインが指定されていました。

```text:20.04でのxorrisoオプション
...
-e boot/grub/efi.img \
...
```

22.04では次のようになりました。

```text:22.04でのxorrisoオプション
...
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b --interval:local_fs:7129428d-7137923d::'ubuntu-22.04-desktop-amd64.iso' \
...
-e '--interval:appended_partition_2_start_1782357s_size_8496d:all::' \
...
```

ここで ``-append_partition`` に指定するStart-Endセクタの指定は、利用するISOイメージによって異なります。
GitHubで公開しているプロジェクトは Live Server ISOイメージを利用するため、次のようになります。

```text:22.04のServer版の場合
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b --interval:local_fs:2855516d-2864011d::'ubuntu-22.04-live-server-amd64.iso' \
```

参考情報に挙げている例では、Desktop版のISOイメージを利用しているため、この数値は異なります。

将来の変更に対応するため、このセクタ数(2855516d-2864011d)はMakefile中で、fdiskコマンドの出力から得ています。

```bash:fdiskコマンドの出力
$ env LANG=C fdisk -l ubuntu-22.04-live-server-amd64.iso

Disk ubuntu-22.04-live-server-amd64.iso: 1.37 GiB, 1466714112 bytes, 2864676 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: C84E0225-4BE7-447A-9FA1-EBF040BDC01F

Device                                Start     End Sectors  Size Type
ubuntu-22.04-live-server-amd64.iso1      64 2855515 2855452  1.4G Microsoft basic data
ubuntu-22.04-live-server-amd64.iso2 2855516 2864011    8496  4.2M EFI System
ubuntu-22.04-live-server-amd64.iso3 2864012 2864611     600  300K Microsoft basic data
```

この下から2行目のEFI SystemタイプのStart-Endの数値(2855516, 2864011)をコマンドラインに展開しています。

現状でもdesktop版とlive server版は入れ替えが可能ですが、将来的にバージョンが上がり、新しいISOイメージが作成されていく中で、これらのセクタ数やサイズを指定している部分は変更が必要になるかもしれません。

Ubuntu 22.04のfdiskはlocaleに応じて翻訳されるため、Makefile中ではLANG=Cを指定しています。

## isolinux関連ファイルがISOイメージに含まれなくなった変更への対応

これも参考資料のxorrisoコマンドラインを20.04と22.04で比較してみます。

```text:20.04のxorrisoオプション
...
-isohybrid-mbr /opt/ubnt/isohdpfx.bin  \
... -b isolinux/isolinux.bin \
...
```

これは22.04ではEFIイメージと同様に、ISOイメージの開始セクタをコピーしています。
isolinux.binはeltorito.imgに置き換わっています。

```text:22.04のxorrisoオプション
...
--grub2-mbr --interval:local_fs:0s-15s:zero_mbrpt,zero_gpt:'ubuntu-22.04-desktop-amd64.iso'
...
-b '/boot/grub/i386-pc/eltorito.img'
```

eltorito.imgを利用することで、isolinux.cfgが不要となり、設定はgrub.cfgだけを編集すれば良くなるので、便利ではあります。

isolinux.bin や isohdpfx.bin ファイルは、isolinuxパッケージを導入することで入手可能です。その他にsyslinux-commonに含まれるldlinux.c32などが必要になります。

ここでは詳細は説明しませんが、GitHubで公開しているプロジェクトには、isolinuxを利用してISOイメージを作成するためのタスクを含めています。利用方法はREADME.mdを参照してください。

# UEFI&MBR両対応イメージの作成と制限

eltorito.imgを利用することで、MBR(BIOS)環境での起動にも対応しています。

ISOイメージ自体は両環境に対応しているため、起動すると自動でMBRとUEFIの違いを認識し、OS導入を開始します。

繰り返しになりますが、UEFI環境とMBR環境で準備しなければいけないパーティションの情報に違いがあるため、自動インストールの実現には user-data の共通化はできず、UEFI版とMBR版で別々のイメージファイルを作成する必要があります。

それぞれの user-data ファイルの違いについて説明します。

## MBR版 user-data の特徴

* ディスクパーティションを作成する際に、``ptable: msdos`` を指定している
* パーティションはLVMに対応させず、swap領域の他には '/'(root)領域を一つだけ作成している

## UEFI版 user-data の特徴

* ``ptable: gpt`` を指定している
* MBR版のパーティション構成に加えて、UEFIブートに対応させるためのESP領域を追加で作成している。

## curtin (storage) 関連の作業について

user-data の中では、storage:セクションのボリュームが大きく、パーティション・ファイルシステム作成等のタスクが集中しています。

### swap関連

swap領域をパーティションの一つとして準備しています。そのため、/swap.imgファイルを利用しなくて良いので、.autoinstall.storage.swap.size を 0 にする必要がありました。

HDDを使っていて外周にswap領域を作らない限り、パーティションにするかファイルにするかは好みだと思います。

また /etc/fstab に swap 領域の設定を加えるためには、type: mount に path: none の指定が必須でした。

```yaml:user-dataからの抜粋(swap)
  storage:
    swap:
      size: 0
    config:
      - id: format-2-swap
        type: mount
        path: none
        device: format-2
        options: pri=1,discard=pages
```

path:行は省略不可です。

Kubernetesのノードにするなどの理由でswap領域を準備する必要がない場合には、user-dataから関連するパーティション情報を削除してください。 storage.swap.size: 0 の指定がないとswapfileが作成されてしまうため、必ず残しておいてください。

### size: -1 指定

最後に作成するパーティションに限り、``size: -1``と指定することで、残り領域を全て割り当てることができます。

```yaml:user-dataからの抜粋(size)
  storage:
    config:
      - id: partition-3
        type: partition
        size: -1
        number: 3
        device: root-ssd
        wipe: superblock
        preserve: false
```

### 導入デバイスの選択方法

これまでSSDが認識されるデバイスが、/dev/sdaだったり、/dev/sdbだったり、接続するHDD・SSDの数によって変化するため導入の自動化はその都度修正が必要でした。

対象によってISOイメージを作り分けていましたが、目的が同じであれば、size: -1 の指定と合わせて、柔軟な運用が可能になります。

```yaml:user-dataからの抜粋(デバイス選択)
  storage:
    config:
      - id: root-ssd
        type: disk
        ptable: gpt
        match:
          size: largest
          ## ssd: true
        wipe: superblock-recursive
        preserve: false
        grub_device: true
        name: "CrucialSSD"
```

現在はHDDとして認識されるVMware上のVMを使って検証作業を行なっているため、size: largest だけを指定していますが、ssd: trueも追加可能です。

これらの指定により、HDDと比較してサイズの小さなSSDの中から最もサイズの大きなSSDをOSの導入対象として選択するといったことが可能になり、より汎用的なイメージが作成可能になります。

## 【重要】user-dataファイル編集時の留意点

ちょっとした変更を行なうためにvimなどを利用すると、インデントを揃えるために簡単にタブ文字が挿入されてしまいます。

boot時に対話的UIが立ち上がった場合など、user-dataの内容が反映されていない挙動を示した時には、まずタブ文字がないことを確認してください。

一般的なLinux distributionにはGNU sedが搭載されていると思うので、``sed -e 's/\t/    /g'``のようなフィルターを通すようにすると良いかもしれません。

# 古いサーバーを利用する際のTips

かなり古いサーバーである富士通製 RX100 S7に使った時には、GRUB経由で起動させることができませんでした。

この場合にはAPU/APU2に対応したisolinuxを利用してbootするISOイメージの作成手順を利用してください。

user-data.mbrを利用する以外には、設定上は特に違いを意識することはないと思います。

```bash:
$ make download
$ make init
$ make init-isolinux

$ ln -fs user-data.mbr config/user-data

$ make setup
$ env LANG=C make geniso-isolinux
```

よほど古くなければGRUBから起動できると思いますが、その場合にはおそらくUEFIへの切り替えができる場合が多いでしょうから、可能であればUEIFを利用した方が良いと思います。

RX100 S7で不具合が発生したこと自体は、後からわかったgrub.cfgにconsole=ttyS0,115200n8を含めていたことが原因かもしれません。これはすぐには検証できませんが、いずれにしても古いシステムであればisolinuxを使う手順が安定していると思いますので、こちらを利用してください。

# 2023/08/04 変更点のまとめ

x270でのインストールに対応するため、次のような変更を行いました。

## grub.cfg

カーネルパラメータに渡していた``console=ttyS0,115200n8``を削除しました。

この他にオリジナルの設定ファイルと同様に``loadfont unicode``などの設定をコピーしています。

## user-data.efi

キーボードレイアウトは変更したいニーズが多そうなので、あらかじめ``keyboard: { layout: us }``設定を加えています。この指定自体はデフォルトですので削除しても影響はありません。

また、インストール作業終了後に再起動をするとインストールプロセスがループする現象を回避するため、``shutdown: poweroff``を指定しています。

この他に不要な設定を削除したり、文字列から特定のブランド名を削除するといった軽微な変更を行いました。

## Makefile

``.PHONY:``によるダミーターゲットの指定を個別に行うように変更しました。

## その他

22.04のイメージをx270などいくつかのハードウェアに適用する際、問題が発生していました。

これはしばらく解決できなかったのですが、結果としてgrub.cfgでカーネルパラメータにconsole=ttyS0,115200n8を指定していたことが原因でした。

これが指定されている間は、システム全体が正常に稼動せず、pingなどにも反応しない状態になります。

これをconsole=tty0 console=ttyS0,115200n8のようにしても解決せず、console=ttyS0の指定そのものを削除する必要がありました。ttyS0自体は存在しないわけではないので、これがシステム全体の稼動にまでどうして影響しているのは良く分かっていません。

# Desktop系ISOイメージの利用について

Issuesで質問がきていたので時間があった時に調べたのですが、次の記事が参考になりそうです。

* [Linux Mint Forums - [Solved] Autoinstall with preseed](https://forums.linuxmint.com/viewtopic.php?t=391307)

ただDesktop版のISOイメージはプロジェクトチーム毎に利用しているフレームワークが異なります。例えばLubuntuは[Calamares - Universal Installer Framework](https://calamares.io/) ([LubuntuチームのGitHubレポジトリ](https://github.com/lubuntu-team/calamares-settings-ubuntu)) を利用しています。

Calamaresはリッチな対話的なインストーラーを提供する汎用的なプロジェクトでとても興味深いですが、自動化についての特別なサポートは提供していません。計画の中にはOEMデプロイメントの中でpre-deliveryのための機能について言及があるため将来的には何かしら出荷前のOS導入を支援する機能が提供される可能性がありますが、現段階では具体的な機能は実装されていません。

このため、お勧めの方法は最低限のUbuntu Serverを導入し、追加パッケージとして**xubuntu-desktoip**や**ubuntu-budgie-desktop**などの*-desktopメタパッケージを導入する方法です。

インストーラーによっては各Flavoursを開発しているチームが個別に最適化を施しているため、Ubuntu Serverをベースとするものとの違いが問題になるかもしれないため、この方法も完全な代替手段ではありませんが現時点ではベストだと思います。

例えば机に並んでいる数十台のPCにUbuntuを導入したいのであれば、インストーラーにこだわるよりもAnsibleなどで継続的に構成が維持できるような環境を構築する方法に注力するべきだと思います。その点ではここで紹介しているsudoできるデフォルトユーザーとopenssh-serverが稼動する最低限のUbuntu Serverを導入する方法は有効なはずです。

# さいごに

20.04ではAlternative ISOイメージが提供されなくなりAutoInstallが必須となりましたが、22.04からはISOイメージの内部の構成に変更が行なわれていることでAutoInstallを利用するための手順全体を見直す必要がありました。

22.04.2がリリースされてようやく安定してきた印象ですが、20.04.xと比較すると以前は問題なかったシステムでもよく分からない挙動を示すことがあります。

grub.cfgへの設定作業の集約など、目的は分かりますが、冗長でも分かりやすい構成を維持してくれた方が、インストーラーをカスタマイズしたい者にとっては良かったのかなとは思います。

作業手順を確立してしまえば大きな問題ではないですが、新しく取り組もうとする人には少し難易度が高くなったかなと感じましたが、これに怯まずKittingしたUbuntuを導入して楽しいコンピューティング環境を構築してください。

以上