最高のLinux(Debian)インストーラを作ろう

#目次
[1.はじめに](#1-はじめに)
[2.入れるアプリを決めよう](#2-入れるアプリを決めよう)
[3.preseed記述例](#3-preseed記述例)
[4.isoの作成とインストール](#4-isoの作成とインストール)
[5.参考文献](#5-参考文献)
[6.注釈](#6-注釈)

コードだけ見たい方は[3.preseed記述例](#3-preseed記述例)をクリック

#1. はじめに 
##1.1.最高のインストーラを作ろう
自動でインストール作業を行ってくれて、欲しいアプリも最初から入っている（且つ、使わないアプリがあまり入っていない）ような最高のISOを作成する。そうした「カスタムISO」を作成するために、preceed.cfgというファイルにインストールの手順を記述していく。

カスタムISOの素体としては、Debian 11 (bullseye)を用いる。Debianはデスクトップ環境なしでのインストールが可能であり、高いカスタマイズ性を持っているからである。他にも、安定性に優れている、歴史が長く規模の大きいディストリビューションであるため情報が多いなどのメリットがある。isoはnon-freeバージョンがおすすめだが、結局有線でインストールしたのでnon-freeでなくても良いのかもしれない。リンクはこちら。→https://cdimage.debian.org/cdimage/unofficial/non-free/cd-including-firmware/11.1.0+nonfree/amd64/iso-cd/ (firmware-11.1.0-amd64-netinst.isoというファイルをインストール)

##1.2. preseedとは
preseed.cfgはDebianやUbuntuにおけるインストーラの事前設定ファイルである。これを用いることで、インストールの自動化・カスタマイズが可能となる。


#2. 入れるアプリを決めよう

##2.1. (推奨)最低限必要なアプリ
「好きなアプリだけを入れたい」と思っても、なんだかんだ言って最低限必要なアプリはあるものだ。まず、基となるISOにはデスクトップ環境が入っていないため、自分でウィンドウマネージャ関連の設定をしなければならない。私はi3 wmというタイル型ウィンドウマネージャを使うことにした。また、ディスプレイマネージャはlightdmにした。最低限インストールするものは以下。
`lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings i3 i3status dmenu xserver-xorg`

また、GUIのファイルマネージャ（とゴミ箱や圧縮解凍, USBの自動マウント）はよく使うので入れておきたい。
`xarchiver thunar gvfs autofs`

基本的な開発ツール・コマンド・プログラミング言語。好みでzshもインストール。元々インストールされているものもあるが、一応明示的に書いておく。
`zsh python3 python3-pip build-essential curl wget git nano vim default-jdk`

ターミナル。自分の好きなものを入れればいいが、私はterminatorを選択した。
`terminator`
（追記）ネットワーク関連。重要。
`network-manager network-manager-gnome`
apt関連のツール。
`software-properties-common apt-transport-https`

日本語フォントと入力環境。font-managerは必須ではないが、フォントファイルを確認・閲覧することができる。
`fcitx fcitx-mozc fonts-noto-cjk font-manager`

音声の出力・設定。
`pulseaudio pavucontrol alsa-utils`

メディアの閲覧に必要なアプリ群。evinceはPDFビューア。fehは軽量画像ビューア。
`evince feh vlc`

ブラウザ。私はchromiumをインストールしたが、firefoxでも良い。拡張機能も一緒に入れておこう。
chromium:
`chromium webext-https-everywhere webext-ublock-origin-chromium`
firefox[^1]:
`firefox-esr webext-https-everywhere webext-ublock-origin-firefox`

その他あると便利なもの。rangerはCUIのファイルマネージャ。screengrabはスクリーンショット機能。w3mはターミナル上で動作するブラウザ。comptonはターミナルを透過するのに使う。
`htop rclone tlp w3m w3m-img ranger compton neofetch aria2
`
##2.2. 好きなアプリを入れていこう
ここからは、好きなアプリや自分が必要だと思うアプリをどんどん入れていこう。

私はパソコンでよく絵を描いたり画像を編集したりするので、Inkscape, GIMP, Kritaをまずはインストールすることにした。また、作曲もLinuxで出来ると嬉しいのでArdourというDAWも入れた。他にも、3DCGにも興味があるのでBlenderも入れたい。
`ardour blender inkscape gimp gimp-gmic krita`

torやproxy関連。
`torbrowser-launcher proxychains tor`

カスタムISOを作成するツール群。[3.インストールの方法](#3-インストールの方法)でも触れる。
`libarchive-tools xorriso p7zip-full gzip`

QEMU(CUIの仮想環境)。
`qemu-system libvirt-clients libvirt-daemon-system `

#3. preseed記述例

以下、preseed.cfgの記述例。
 
- https://www.debian.org/releases/bullseye/example-preseed.txt 
- https://qiita.com/ajitama/items/4ca2c6db7bfe29250d42

を参考にした。

なお、preseed.cfg中の記述されていないかコメントアウトされている行程については、通常の手動インストールと同じように処理される。また、基本的にディスク全体を初期化するので注意。

```
#### Contents of the preconfiguration file (for bullseye)
### Localization
# Preseeding only locale sets language, country and locale.

# The values can also be preseeded individually for greater flexibility.
d-i debian-installer/language string ja
d-i debian-installer/country string JP
d-i debian-installer/locale string ja_JP.UTF-8
d-i localechooser/supported-locales ja_JP.UTF-8
d-i console-setup/ask_detect boolean false
d-i console-setup/Alayoutcode string ja
d-i console-setup/charmap select UTF-8

# Keyboard selection.
d-i console-keymaps-at/keymap select jp
d-i keyboard-configuration/layoutcode string jp
d-i keyboard-configuration/modelcode jp106
d-i keyboard-configuration/layout select Japanese
d-i keyboard-configuration/variant select Japanese
d-i keyboard-configuration/toggle select No toggling

### Network configuration
d-i netcfg/choose_interface select auto

# To pick a particular interface instead:
#d-i netcfg/choose_interface select eth1

#d-i netcfg/get_hostname string your-PC-name
#d-i netcfg/get_domain string 

# If non-free firmware is needed for the network or other hardware, you can
# configure the installer to always try to load it, without prompting. Or
# change to false to disable asking.
d-i hw-detect/load_firmware boolean true

### Network console

### Mirror settings
d-i mirror/country string manual
d-i mirror/http/hostname string deb.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string

### Account setup
# Skip creation of a root account (normal user account will be able to
# use sudo).
d-i passwd/root-login boolean false
# Alternatively, to skip creation of a normal user account.
d-i passwd/make-user boolean true 

#Rootパスワードを設定するかどうか決める
# Root password, either in clear text
#d-i passwd/root-password password r00tme
#d-i passwd/root-password-again password r00tme
# or encrypted using a crypt(3)  hash.
#d-i passwd/root-password-crypted password [crypt(3) hash]

# To create a normal user account.
#自分のusernameやパスワードを書いてコメントアウトを外すと入力を自動化できる
#d-i passwd/user-fullname string yourname
#d-i passwd/username string yourname
# Normal user's password, either in clear text
#d-i passwd/user-password password xxxxxxxx
#d-i passwd/user-password-again password xxxxxxxx

### Clock and time zone setup
# Controls whether or not the hardware clock is set to UTC.
d-i clock-setup/utc boolean false

# You may set this to any valid setting for $TZ; see the contents of
# /usr/share/zoneinfo/ for valid values.
d-i time/zone string Asia/Tokyo

# Controls whether to use NTP to set the clock during the install
d-i clock-setup/ntp boolean true
# NTP server to use. The default is almost always fine here.
d-i clock-setup/ntp-server string ntp.nict.jp

### Partitioning
## Partitioning example

# If one of the disks that are going to be automatically partitioned
# contains an old LVM configuration, the user will normally receive a
# warning. This can be preseeded away...
d-i partman-lvm/device_remove_lvm boolean true
# The same applies to pre-existing software RAID array:
d-i partman-md/device_remove_md boolean true

# Alternatively, you may specify a disk to partition. If the system has only
# one disk the installer will default to using that, but otherwise the device
# name must be given in traditional, non-devfs format (so e.g. /dev/sda
# and not e.g. /dev/discs/disc0/disc).
# For example, to use the first SCSI/SATA hard disk:
#d-i partman-auto/disk string /dev/sda
#d-i partman-auto/disk string /dev/nvme0n1
# In addition, you'll need to specify the method to use.
#d-i partman-auto/init_automatically_partition select Guided - use entire disk
# The presently available methods are:
# - regular: use the usual partition types for your architecture
# - lvm:     use LVM to partition the disk
# - crypto:  use LVM within an encrypted partition
#d-i partman-auto/method string lvm
d-i     partman-auto/method string regular
#LVMは使わない
d-i     partman-lvm/confirm boolean false
# You can define the amount of space that will be used for the LVM volume
# group. It can either be a size with its unit (eg. 20 GB), a percentage of
# free space or the 'max' keyword.
#d-i partman-auto-lvm/guided_size string max

# You can choose one of the three predefined partitioning recipes:
# - atomic: all files in one partition
# - home:   separate /home partition
# - multi:  separate /home, /var, and /tmp partitions
d-i partman-auto/choose_recipe select atomic

# Set the default filesystem
d-i partman/default_filesystem string ext4

# Install without swap space
d-i partman-basicfilesystems/no_swap boolean false

# This makes partman automatically partition without confirmation, provided
# that you told it what to do using one of the methods above.
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true 
d-i partman/confirm_nooverwrite boolean true
d-i partman-md/confirm boolean true

### Base system installation
d-i base-installer/kernel/image string linux-genetic

### Apt setup
# You can choose to install non-free and contrib software.
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
d-i apt-setup/use_mirror boolean true
d-i apt-setup/security_host string security.debian.org



### Package selection
#デスクトップ環境を選択しない
tasksel tasksel/first multiselect none

#ここから先程決めたアプリをインストールしていく。まずは重要なアプリをインストール
d-i pkgsel/include string lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings i3 i3status dmenu xserver-xorg\
xarchiver thunar gvfs autofs \
zsh python3 python3-pip build-essential curl wget git nano vim default-jdk \
network-manager network-manager-gnome \
terminator \
software-properties-common apt-transport-https\
fcitx fcitx-mozc fonts-noto-cjk font-manager \
pulseaudio pavucontrol alsa-utils \
evince feh vlc \
chromium webext-https-everywhere webext-ublock-origin-chromium \
#firefox-esr webext-https-everywhere webext-ublock-origin-firefox \
htop rclone tlp w3m w3m-img ranger compton neofetch aria2 \
#好きなアプリをインストール
ardour blender inkscape gimp gimp-gmic krita \
torbrowser-launcher proxychains tor \
libarchive-tools xorriso p7zip-full gzip \
qemu-system libvirt-clients libvirt-daemon-system

d-i pkgsel/upgrade select none 

popularity-contest popularity-contest/participate boolean false 


### Boot loader installation

d-i grub-installer/bootdev  string /dev/sda
d-i grub-installer/grub2_instead_of_grub_legacy boolean true 
d-i grub-installer/only_debian boolean true

### Finishing up the installation
#late_commandではコマンドやスクリプトを実行することが出来る
#詳細はhttps://www.debian.org/releases/stable/s390x/apbs05.ja.htmlを参照
#Google Chrome, Visual Studio Code, Steamをインストールする
d-i preseed/late_command string in-target mkdir ~/deb ; \
in-target wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -O ~/deb/google-chrome-stable_current_amd64.deb ; \
in-target wget "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64" -O ~/deb/vscode-stable.deb ; \
in-target wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb -O ~/deb/steam.deb ; \
apt-install apt ; \
in-target apt install -y ~/deb/google-chrome-stable_current_amd64.deb ; \
in-target apt install -y ~/deb/vscode-stable.deb ; \
in-target apt install -y ~/deb/steam.deb ; \
in-target rm -r ~/deb

d-i finish-install/reboot_in_progress note
d-i debian-installer/exit/poweroff boolean true

```


#4. isoの作成とインストール

##4.1.順序
[DebianInstaller Preseed EditIso](https://wiki.debian.org/DebianInstaller/Preseed/EditIso "DebianInstaller Preseed EditIso")よりコードを引用。分からないことがあれば、このリンクを見れば大体解決すると思う。
>###Extracting the Initrd from an ISO Image
>
```
bsdtar -C DESTINATION -xf debian-10.2.0-i386-netinst.iso
xorriso -osirrox on -indev debian-10.2.0-i386-netinst.iso -extract / DESTINATION
7z x -oDESTINATION debian-10.2.0-i386-netinst.iso
```
>###Adding a Preseed File to the Initrd
>
```
chmod +w -R isofiles/install.386/
gunzip isofiles/install.386/initrd.gz
echo preseed.cfg | cpio -H newc -o -A -F isofiles/install.386/initrd
gzip isofiles/install.386/initrd
chmod -w -R isofiles/install.386/
```
>###Regenerating md5sum.txt
>
```
cd isofiles
chmod +w md5sum.txt
find -follow -type f ! -name md5sum.txt -print0 | xargs -0 md5sum > md5sum.txt
chmod -w md5sum.txt
cd ..
```

また、以下は[RepackBootableISO](https://wiki.debian.org/RepackBootableISO#Determine_those_options_which_need_to_be_adapted_on_amd64_or_i386 "RepackBootableISO")を参考にした。
###ブータブルISOの作成
```
dd if="$orig_iso" bs=1 count=432 of="$mbr_template"
sudo xorriso -as mkisofs \
   -r -V 'Debian 11.1.0 amd64 n' \
   -o "$new_iso" \
   -J -J -joliet-long -cache-inodes \
   -isohybrid-mbr "$mbr_template" \
   -b isolinux/isolinux.bin \
   -c isolinux/boot.cat \
   -boot-load-size 4 -boot-info-table -no-emul-boot \
   -eltorito-alt-boot \
   -e boot/grub/efi.img \
   -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \
   "$new_files"
```
上から順にコードを実行していけば、preseed.cfgの反映されたブータブルISOを作成することが出来る。
##4.2.コード全体
以下のコード全体を貼り付けるなりshファイルにするなりして実行すれば、一気にブータブルISOを作成出来る。

```
#変数を決める
#currentは好きなファイルパスを指定する
current=~/Downloads/test
orig_iso="$current"/debian11.iso
new_files="$current"/isofiles
new_iso="$current"/new.iso
mbr_template=isohdpfx.bin

#Extracting the Initrd from an ISO Image
cd "$current"
mkdir "$new_files"
bsdtar -C "$new_files" -xf "$orig_iso"
sudo xorriso -osirrox on -indev "$orig_iso" -extract / "$new_files"
echo A | sudo 7z x -oisofiles "$orig_iso"

#Adding a Preseed File to the Initrd
#install.amdのところはinstall.386の場合もあるので適宜変更する
sudo chmod +w -R "$new_files"/install.amd/
sudo gunzip "$new_files"/install.amd/initrd.gz
sudo echo preseed.cfg | sudo cpio -H newc -o -A -F "$new_files"/install.amd/initrd
sudo gzip "$new_files"/install.amd/initrd
sudo chmod -w -R "$new_files"/install.amd/

#Regenerating md5sum.txt
cd "$new_files"
sudo chmod +w md5sum.txt
sudo find -follow -type f ! -name md5sum.txt -print0 | sudo xargs -0 md5sum > sudo md5sum.txt
sudo chmod -w md5sum.txt
cd ..

dd if="$orig_iso" bs=1 count=432 of="$mbr_template"

#ブータブルISOの作成
sudo xorriso -as mkisofs \
   -r -V 'Debian 11.1.0 amd64 n' \
   -o "$new_iso" \
   -J -J -joliet-long -cache-inodes \
   -isohybrid-mbr "$mbr_template" \
   -b isolinux/isolinux.bin \
   -c isolinux/boot.cat \
   -boot-load-size 4 -boot-info-table -no-emul-boot \
   -eltorito-alt-boot \
   -e boot/grub/efi.img \
   -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \
   "$new_files"
```
ISOができたら、`dd`コマンドを使ったり[balenaetcher](https://www.balena.io/etcher/)を使ったりしてISOをUSBなどに焼く。
##4.3.インストール時の注意

- インストール時は有線でネットワーク接続をしておくのをおすすめする。
- USBを挿して起動したら、Advanced options => Automated installの順にクリックする(Graphical automated installではない)。
- 実機にインストールする前に、VirtualBoxやQEMUなどの仮想環境でテストしておくと良い。

#5. 参考文献
- https://www.debian.org/releases/bullseye/example-preseed.txt
- DebianInstaller Preseed EditIso https://wiki.debian.org/DebianInstaller/Preseed/EditIso
- RepackBootableISO https://wiki.debian.org/RepackBootableISO
- preseedメモ https://qiita.com/ajitama/items/4ca2c6db7bfe29250d42
- B.5. 高度なオプション https://www.debian.org/releases/stable/s390x/apbs05.ja.html

#6. 注釈
[^1]: `d-i apt-setup/security_host string security.debian.org`とpreseed.cfgに書いておく必要がある。