自分だけの Linux Liveイメージを作る
はじめに
平素は大変お世話になっております。
クイックガードのパー子です。
日夜 ITシステムの構築・運用に従事していると、稀に Linux の Liveイメージを使いたくなることがあります。
この記事では、Debian Live Project の成果物を用いて、独自にカスタマイズした Liveイメージを作成する手順を解説します。
参考文献
Liveイメージの作成に関する公式マニュアルです。
必要な情報は大体ここに載っています。
作業環境
Intel MacBook上に UTM で立ち上げた Debian 12 (bookworm) でビルドします。
起動システムや格納するメディアを問わない (※) Liveイメージを作成し、同UTM上で起動するまでを目標とします。
※ マシンの起動システムとして UEFI と BIOS の両方をサポートし、CD/DVD と USBメモリのどちらからでも起動できること。
作成手順
事前準備
live-buildパッケージをインストールしておきます。
$ sudo apt-get install live-build
続いて作業ディレクトリを用意します。
以降の作業はこのディレクトリの中で行います。
$ mkdir ./work
$ cd ./work/
初期化
lb config
コマンドで作業ディレクトリを初期化します。
$ lb config \
--distribution 'bookworm' \
--archive-areas 'main non-free non-free-firmware contrib' \
--bootappend-live 'boot=live components keyboard-layouts=jp quiet splash'
初期化すると作業ディレクトリ内に以下のツリーが作成されます。
特に ./config/
が重要で、ここに様々なファイルを配置することで Liveイメージをカスタマイズできます。
./
├── auto/
├── config/
│ ├── apt/
│ ├── archives/
│ ├── binary
│ ├── bootloaders/
│ ├── bootstrap
│ ├── chroot
│ ├── common
│ ├── debian-installer/
│ ├── hooks/
│ │ ├── live/
│ │ │ ├── 0010-disable-kexec-tools.hook.chroot -> /usr/share/live/build/hooks/live/0010-disable-kexec-tools.hook.chroot*
│ │ │ └── 0050-disable-sysvinit-tmpfs.hook.chroot -> /usr/share/live/build/hooks/live/0050-disable-sysvinit-tmpfs.hook.chroot*
│ │ └── normal/
│ │ ├── 1000-create-mtab-symlink.hook.chroot -> /usr/share/live/build/hooks/normal/1000-create-mtab-symlink.hook.chroot*
│ │ ├── ...
│ │ └── 9020-remove-man-cache.hook.chroot -> /usr/share/live/build/hooks/normal/9020-remove-man-cache.hook.chroot*
│ ├── includes/
│ ├── includes.binary/
│ ├── includes.bootstrap/
│ ├── includes.chroot_after_packages/
│ ├── includes.chroot_before_packages/
│ ├── includes.installer/
│ ├── includes.source/
│ ├── package-lists/
│ │ └── live.list.chroot
│ ├── packages/
│ ├── packages.binary/
│ ├── packages.chroot/
│ ├── preseed/
│ ├── rootfs/
│ └── source
└── local/
└── bin/
lb config
コマンドのパラメータの意味は次のとおりです。
パラメータ | 説明 |
---|---|
--distribution | Liveイメージのバージョン |
--archive-areas | 利用するパッケージの アーカイブ領域 |
--bootappend-live | Kernel の起動パラメータ |
–distribution
Liveイメージのバージョンとして bookworm
(Debian 12) を指定します。
(未指定の場合は buster
(Debian 10) がデフォルトです。)
–archive-areas
近年の Debian では non-free なファームウェアは non-free-firmware
で配布される ようになりました。
Wi-Fi を利用する場合などに必要となるので、お馴染みの main
non-free
contrib
に加えてこれを指定します。
–bootappend-live
Liveイメージが起動する際、live-boot および live-config という、システムのブートと初期化を助けるスクリプト群が実行されます。
この挙動を Kernel の起動パラメータで調整することができます。
パラメータ | 説明 |
---|---|
boot=live | live-boot/live-config の有効化 |
components (または live-config.components ) | live-config の全コンポーネントを有効化 |
keyboard-layouts=jp (または live-config.keyboard-layouts=jp ) | キーボードの配列を指定 |
まず boot=live
を記述することで live-boot と live-config が有効化されます。
live-config では目的とする処理ごとにスクリプト・ファイルが分かれており、それを コンポーネントと呼んでいます。
スクリプト は Liveイメージの /lib/live/config/
に配置され、現時点では以下の順序で適用されます。
(番号の若いものが先に実行されます。)
# | コンポーネント |
---|---|
0005 | nss-systemd |
0010 | debconf |
0020 | hostname |
0030 | live-debconfig_passwd |
0030 | user-setup |
0040 | sudo |
0050 | locales |
0070 | tzdata |
0080 | gdm3 |
0085 | sddm |
0090 | kdm |
0100 | lightdm |
0110 | lxdm |
0120 | nodm |
0130 | slim |
0140 | xinit |
0150 | keyboard-configuration |
1020 | gnome-panel-data |
1030 | gnome-power-manager |
1040 | gnome-screensaver |
1050 | kaboom |
1060 | kde-services |
1080 | policykit |
1090 | ssl-cert |
1110 | anacron |
1120 | util-linux |
1130 | login |
1140 | xserver-xorg |
1160 | openssh-server |
1170 | xfce4-panel |
1180 | xscreensaver |
1190 | broadcom-sta |
9990 | hooks |
9995 | nss-systemd |
キーボード配列として指定できる値は /usr/share/X11/xkb/rules/base.lst
に列挙されています。
日本語キーボードの場合は jp
です。
/usr/share/X11/xkb/rules/base.lst
...
! layout
us English (US)
...
jp Japanese
...
他にも多数の起動パラメータが存在します。
詳細は各パッケージの man (live-boot / live-config) を参照してください。
ブートローダ
ブートローダに関する設定を変更します。
- タイムアウト
- スプラッシュ画像
ブートローダの設定ファイルを作業ディレクトリ内の ./config/bootloaders/
配下に配置することで変更できます。
なお、設定ファイルの雛形は /usr/share/live/build/bootloaders/<ブートローダの種類>/
配下に格納されているので、これを加工して使います。
タイムアウト
Liveイメージを起動すると、デフォルトでは起動メニューが表示され、選択されるまで待ち合わせます。
これを変更し、無限に待ち合わせるのではなく、指定の秒数経過 (今回は 5秒) で自動的にデフォルトのエントリーが選択されるようにします。
補足
環境によっては 起動メニューが表示されない ことがあります。
後述するように、ディスプレイ設定を調整することで解消する可能性があるようです。
まずは UEFI用のブートローダである GRUB の設定ファイルを配置します。
$ mkdir ./config/bootloaders/grub-pc
$ {
cat /usr/share/live/build/bootloaders/grub-pc/config.cfg
echo 'set timeout_style=menu'
echo 'set timeout=5'
} > ./config/bootloaders/grub-pc/config.cfg
同様に、BIOS のために ISOLINUX の設定ファイルを配置します。
$ mkdir ./config/bootloaders/isolinux
$ cat /usr/share/live/build/bootloaders/isolinux/isolinux.cfg \
| sed -E 's/^timeout 0/timeout 50/' \
> ./config/bootloaders/isolinux/isolinux.cfg
補足
ISOLINUX のタイムアウト値は 0.1秒刻みのため、5秒の場合は 50
を指定します。
メニュー画面が表示されない場合:
今回の実行環境では、BIOS で起動した場合、デフォルトの設定のままではメニュー画面がうまく表示されませんでした。
(代わりに “Guest has not initialized the display (yet).” というメッセージが出続けます。)
解決方法としては、UTM の仮想マシン設定画面の “ディスプレイ” » “仮想ディスプレイカード” を VGA
あたりに変更することで表示されるようになります。
スプラッシュ画像
メニュー画面に表示されるスプラッシュ画像を好みのものに差し替えます。
./config/bootloaders/syslinux_common/splash.svg
として配置すれば GRUB と ISOLINUX の両方に反映されます。
$ mkdir ./config/bootloaders/syslinux_common
$ cp /PATH/TO/splash.svg ./config/bootloaders/syslinux_common/
PNG でもよいようですが、その場合は 640x480ピクセル にするとよさそうです。
When modifying one of the default themes, if you want to use a personalized background image that will be displayed together with the boot menu, add a splash.png picture of 640x480 pixels.
なお、SVGファイルには @DISTRIBUTION@
や @DATE@
などのプレースホルダを含めることができるようです。
(詳細は /usr/lib/live/build/binary_syslinux
の処理内容を確認してください。)
パッケージ
Liveイメージにプレインストールしておくパッケージを指定します。
./config/package-lists/<任意の名称>.list.chroot
というファイルを作成し、1行1パッケージで列挙します。
今回は OpenSSHサーバを入れて、SSH でログインできるようにしてみます。
$ echo 'openssh-server' > ./config/package-lists/default.list.chroot
ブート・フック
先に説明した ように、システムが起動すると /lib/live/config/
配下のスクリプトが順番に実行されます。
OpenSSHサーバをインストールしても、標準コンポーネントの 1つである 1160-openssh-server
により パスワード認証が無効化されてしまう ため、認証用の設定を施さないと SSH でログインできません。
セキュリティ的には鍵や証明書を用いるのが望ましいのですが、今回は簡便のためにパスワード認証を復活させることにします。
以下のスクリプトを追加の live-configコンポーネントとして配置することで実現します。
1161-allow-password-ssh
#!/bin/sh
echo -n ' allow-password-ssh'
sed -i -E 's/^PasswordAuthentication no$/PasswordAuthentication yes/' /etc/ssh/sshd_config
Liveイメージにファイルを追加するには、目的のファイルを ./config/includes.chroot_after_packages/
配下にツリー構造を保って格納するだけで OK です。./config/includes.chroot_after_packages/
が Liveシステムのルート・ディレクトリ /
に相当するため、上記スクリプトの配置パスは ./config/includes.chroot_after_packages/lib/live/config/1161-allow-password-ssh
となります。
$ mkdir -p ./config/includes.chroot_after_packages/lib/live/config
$ install -m 0755 /PATH/TO/1161-allow-password-ssh ./config/includes.chroot_after_packages/lib/live/config/1161-allow-password-ssh
ビルド
カスタマイズが完了したら、lb build
コマンドで ISOファイルを作成します。
$ sudo lb build
補足
chroot などを実行するので root権限が必要です。
作成には 15分ほどかかります。
完了すると ./live-image-amd64.hybrid.iso
というファイルが生成されます。
起動する
出来上がった Liveイメージを UTM で起動してみましょう。
起動パターンは以下の 4つです。
起動システム | メディア |
---|---|
UEFI | CD/DVD |
UEFI | USBメモリ |
BIOS | CD/DVD |
BIOS | USBメモリ |
起動システムは設定画面の “QEMU” » “UEFI起動” で切り替えます。
起動メディアは、同じく “ドライブ” で変更できます。
“イメージの種類” と “インターフェイス” は以下の組み合わせにします。
メディア | イメージの種類 | インターフェイス |
---|---|---|
CD/DVD | CD/DVD (ISO) イメージ | IDE |
USBメモリ | ディスクイメージ | USB |
UEFI & CD/DVD
正常に起動しました。
これは GRUB のメニュー画面ですね。
スプラッシュ画像も意図どおりのものです。
何もキーを押さないと 5秒でタイムアウトして自動的にデフォルト (= 一番上) のエントリーで OS が起動します。
そのまま OS を立ち上げて、SSH でログインすることもできました。
補足
ユーザ名とパスワードは user
/ live
です。
UEFI & USBメモリ
USBメモリからでも問題なく起動できました。
CD/DVD との差異は特に見られません。
BIOS & CD/DVD
今となっては UEFI に取って代わられてあまり見かけなくなりましたが、レガシーな BIOS でも起動できることを確認しました。
GRUB ではなく、ISOLINUX によるメニュー画面です。
BIOS & USBメモリ
こちらも問題なしです。
CD/DVD との違いはありません。
もっとカスタマイズしたい
今回の要件には含まれていませんでしたが、以下のようなカスタマイズも検討されることが多いかと思います。
ユーザ名を変更する
Kernel の起動パラメータで変更できます。
$ lb config --bootappend-live 'boot=live components username=<ユーザ名>'
パスワードはブート・フックで変更します。
/usr/share/doc/live-config/examples/hooks/
に passwd
というスクリプト があるので、これを ./config/includes.chroot_after_packages/lib/live/config/2000-passwd
などと配置することで起動時にパスワードの変更プロンプトが表示されるようになります。
…と、上記のように 公式マニュアル には書かれているのですが、試してみたところプロンプトがうまく表示されずに起動途中で止まってしまいました。
インタラクティブにパスワードを指定する必要がなければ chpasswdコマンドで固定値に変更してしまってもよいかもしれません。
ユーザ名は Kernel の起動パラメータから拾います。
(/proc/cmdline
から直接取得してもよいですし、環境変数 LIVE_CONFIG_CMDLINE
にも同じものが格納されています。)
2000-chpasswd
#!/bin/sh
echo -n ' 2000-chpasswd'
for _PARAMETER in ${LIVE_CONFIG_CMDLINE}; do
case "${_PARAMETER}" in
live-config.username=*|username=*)
LIVE_USERNAME="${_PARAMETER#*username=}"
;;
esac
done
echo "${LIVE_USERNAME:-user}"':Pa$$w0rd' | chpasswd
ロケール/タイムゾーンを変更する
ユーザ名と同じく Kernel の起動パラメータで変更できます。
$ lb config --bootappend-live 'boot=live components locales=<ロケール> timezone=<タイムゾーン>'
デフォルトはそれぞれ en_US.UTF-8
/ UTC
です。
書き込みを永続化する
Liveイメージのデータは読み取り専用のファイル・システムに格納されており、稼働している間に加えた変更はメモリ上に保持されます。
そのため、再起動すると変更内容が失われてしまうのですが、焼き込んだメディア (= USBメモリなど) の空き領域を活用することで永続的に保持できるようになります。
ここでは仮想的な USBメモリとしてファイルに Liveイメージを焼き込み、同ファイル上に永続化領域をセットアップしてみます。
まず、永続化機能を使用するためには Kernel起動パラメータに persistence
を含める必要があるため、Liveイメージを作り直します。
$ lb config \
--distribution 'bookworm' \
--archive-areas 'main non-free non-free-firmware contrib' \
--bootappend-live 'boot=live components persistence keyboard-layouts=jp quiet splash'
このイメージを焼き込んだ仮想USBメモリ live-image-amd64.hybrid.img
を生成します。
サイズは、Liveイメージが 630MiB程度なので、1GiB とします。
$ cp ./live-image-amd64.hybrid.iso ./live-image-amd64.hybrid.img
$ truncate -s '1G' ./live-image-amd64.hybrid.img
$ ls -gGh ./live-image-amd64.hybrid.*
-rw-r--r-- 1 1.0G Feb 20 09:43 ./live-image-amd64.hybrid.img
-rw-r--r-- 1 628M Feb 20 09:43 ./live-image-amd64.hybrid.iso
続いて当該ファイルを loopデバイスに紐付けます。
$ sudo losetup -f
/dev/loop0
$ sudo losetup /dev/loop0 ./live-image-amd64.hybrid.img
永続化用のパーティションを作成します。
Liveイメージの正確なサイズは 658,505,728 Bytes で、それ以降の領域をすべて永続化用パーティションにします。
$ ls -gG ./live-image-amd64.hybrid.iso
-rw-r--r-- 1 658505728 Feb 20 09:43 ./live-image-amd64.hybrid.iso
$ sudo parted /dev/loop0
GNU Parted 3.5
Using /dev/loop0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes.
Ignore/Cancel? ignore
Model: Loopback device (loopback)
Disk /dev/loop0: 4295MB
Sector size (logical/physical): 2048B/512B
Partition Table: mac
Disk Flags:
Number Start End Size File system Name Flags
1 2048B 6143B 4096B Apple
2 379kB 5589kB 5210kB EFI
(parted) mkpart
Partition name? []?
File system type? [ext2]? ext4
Start? 658505728B
End? 100%
Error: Too many primary partitions.
セクター・サイズが一致しない、総容量がおかしい、パーティション・テーブルの形式は mac
でいいのかなど、いろいろ気になる点はありますが、結局 “Too many primary partitions.” と怒られてパーティションの作成に失敗してしまいました。
う〜ん、公式マニュアル では軽いノリでパーティションを作成しているのですが…。
後述しますが、今回の Liveイメージは isohybrid というテクニックを用いてビルドされており、パーティション・テーブルの構造がどうにも胡散くさいように思います。
そこで、安定していそうな hdd
形式 で試してみることにします。
$ lb config \
--distribution 'bookworm' \
--binary-image 'hdd' \
--archive-areas 'main non-free non-free-firmware contrib' \
--bootappend-live 'boot=live components persistence keyboard-layouts=jp quiet splash'
この設定で作成した Liveイメージを用いて改めてトライしてみます。
$ sudo parted /dev/loop0
GNU Parted 3.5
Using /dev/loop0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: Loopback device (loopback)
Disk /dev/loop0: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 724MB 722MB primary fat32 boot
(parted) mkpart primary ext4 723517440B 100%
(parted) print
Model: Loopback device (loopback)
Disk /dev/loop0: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 724MB 722MB primary fat32 boot
2 724MB 1074MB 350MB primary ext4 lba
(parted) quit
Information: You may need to update /etc/fstab.
いけました。
作成したパーティションを ext4 でフォーマットします。
ボリューム・ラベルは persistence
とする必要があります。
$ sudo mkfs.ext4 -L 'persistence' /dev/loop0p2
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 342016 1k blocks and 85344 inodes
Filesystem UUID: 463b74a6-691a-46c9-9b75-0778ca5e55ba
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
最後に永続化用の設定ファイルである persistence.conf
をルートに配置します。
ここでは /home/
以下を永続化するようにしてみます。
$ sudo mount /dev/loop0p2 /mnt/
$ echo '/home' | sudo tee /mnt/persistence.conf > /dev/null
$ sudo umount /mnt/
$ sudo losetup -d /dev/loop0
以上で設定完了です。
UTM の起動モードが BIOS となっていること、および、ドライブ設定の “読み出しのみ” のチェックが外れていることを確認したうえで起動してみましょう。/home/
配下への変更が、再起動した後も保持されているはずです。
補足
hdd
形式の Liveイメージは、パーティション形式からもわかるとおり、UEFI では起動できません。
あくまで isohybrid を認識できない (レガシーな?) マシン用のイメージということでしょうか。
デフォルトの挙動では、初回起動時に指定したツリーが丸ごと永続化領域へコピーされるようです。/usr/
などへの変更は Liveイメージとの差分のみ保持したいはずなので、そのようなときは /usr union
などとすればよいです。
(詳細は man を確認してください。)
また、暗号化 することもできるようです。
Apendix
isohybrid
Debian の Liveイメージは、デフォルトでは isohybrid というテクニックを用いて作成されます。
光学メディアとストレージ・デバイスでは起動の仕組みが異なるため、通常はそれぞれの起動メディア専用のイメージを別々に用意する必要があります。
この手間を解消して、単一のバイナリで両方のメディアに対応するのが isohybrid です。
isohybrid の肝は、ISO 9660ファイル・システムの先頭にある 32KiB の未使用領域 です。
この領域は光学ドライブから読み込む場合は無視されるため、自由なデータを書き込むことができます。
光学メディアとして標準的な ISO 9660形式のファイル・システムを維持しながら、先頭の未使用領域にストレージ・デバイス用のブートローダやパーティション・テーブルを書き込むことでハイブリッドなイメージを実現しているのです。
UEFI
UEFIシステムにおいて、ブートローダは ESP (= EFI System Partition) と呼ばれるパーティションに格納されている必要があります。
そこで、ISOファイル・システム上に UEFI用のブートローダを含んだイメージ (= ブート・イメージ) を配置しておき、そのイメージが占有する領域を仮想的な ESPパーティションとしてパーティション・テーブルに登録します。
USBメモリなどのストレージ・デバイスから起動すると、UEFI はパーティション・テーブルの記述に従ってこのブート・イメージを ESP と認識して起動処理を進めるのです。
BIOS
BIOS の場合は MBR (= Master Boot Record) に格納されたブートローダが使用されます。
UEFI で使用されるパーティション・テーブル (= GPT; GUID Partition Table) の先頭には Protective MBR という従来の MBR と同サイズの領域が確保されているため、UEFI用の設定を破壊することなく共存できます。
ちなみに、光学メディアから起動する場合でも UEFI と BIOS で異なるブートローダが使用されますが、これは Bootable CD のための規格である El Torito に基づいて複数のブートローダを設置しているようです。
まとめ
以上、Debian の Liveイメージを自作する手順をご紹介しました。
オリジナルの Liveイメージを作成し、起動システム (UEFI or BIOS) やメディア (CD/DVD or USBメモリ) を問わず起動できることを確認しました。
isohybridイメージだと変更の永続化がうまくいきませんでしたが、もし成功したという方がいらっしゃいましたらぜひ教えてください。
今後ともよろしくお願い申し上げます。