Linux Mint 20.2をVirtualBoxからPXEでネットワークインストール

## はじめに
はじめての投稿になります。宜しくお願いします。

Windows10が厳しくなってきてLinuxMint20への入れ替えを考えています。
USBメモリやDVD-Rから起動できればいいのですが
何故かBIOSでブート順を変更できず（グレーアウトされている）
かろうじてPXEからのインストールは選択できるようなので
別のPCでPXEサーバを立ててみようと思いました。

インターネットでいろいろ調べましたが、結構ハマりましたので
何かの役に立てばと思い共有します。

## 準備するもの
- サーバとなるPC (空き容量100GB以上)
    - VirtualBox (インストール方法は割愛します）
    - VirtualBox上にUbuntuDesktop20.04LTS (これもインストール方法割愛)
- サーバとインストール先PCをつなぐルータ (DHCPサーバ機能を使用します)
- インストール先となるPC

## おおまかな手順
1. PXEサーバとなるVirtualBox上のUbuntuに必要なものをインストールする
1. 試験のため、PXEサーバのネットワーク設定を変更する
1. 試験用の仮想PCをVirtualBox上に作成し、動作を確認する
1. 本番用にネットワークを設定し、ターゲットPCにインストールを実施する

## 【手順１】 PXEサーバのセットアップ
まず、今回インストールしたいLinuxMintのISOファイルをダウンロードします。
今回はMATEを使用します。[こちらからダウンロードしてください](https://www.linuxmint.com/edition.php?id=289) 
私はVirtualBoxでのマウント操作に馴染んでいるのでホスト側にダウンロードしました。後でメディアに移すのも楽ですし。

---
ここからは仮想マシンのUbuntu上の作業になります。
インストールするパッケージは以下になります。

- dnsmasq : 今回はProxyDHCPおよびTFTPサーバとして使用します。
- nfs-kernel-server : 今回はNFSにてインストールするファイルを共有します。
- syslinux-common : ブートに必要な各種ファイルがインストールされます。
- pxelinux : PXEブートに必要なファイルがインストールされます。

これらをインストールするために以下のコマンドを端末で実行してください。

```bash:パッケージのインストール
sudo apt update
sudo apt install dnsmasq nfs-kernel-server syslinux-common pxelinux -y
```

これからdnsmasqの設定を行うため、一旦サービスを停止します。
（インストールと同時に自動的に起動されていると思います）

```bash:dnsmasqの停止
sudo systemctml stop dnsmasq
# 再起動時に自動的に起動するのも停止しておく
sudo systemctl disable dnsmasq
```

PXEブート時のTFTPサーバのコンテンツルートを `/var/lib/tftpboot` とします。
ブートに必要なファイルをコンテンツルートに紐つけます。

```bash:ブートに必要なファイルのリンクを貼る
cd /var/lib/tftpboot
sudo mkdir -p bios
sudo ln -s /usr/lib/syslinux/modules/bios/* bios
sudo ln -s /usr/lib/PXELINUX/* bios
```

これは必須ではありませんが、ターゲットPCのチェック用に **Memtest86+** を入れています。
[Memtest86+ V5.31b](https://www.memtest.org/download/5.31b/memtest86+-5.31b.bin.gz) をダウンロード＆解凍したものを `$HOME/Downloads` に入れた後、以下の操作を行いました。

```bash:Memtest86+の導入
cd /var/lib/tftpboot
sudo mkdir -p memtest
# 拡張子があるとうまく動かないようなので外してコピーする
cd memtest
sudo cp $HOME/Downloads/memtest86+-5.31b.bin memtest86+-5.31b
```

PXEブートの初期に上記の **Memtest86+** と **LinuxMintインストール** の起動を選択できる設定を加えます。これを応用すれば複数の種類のインストールに対応できるサーバもできると思います。
これは `/var/lib/tftpboot/pxelinux.cfg` フォルダを作成し、その配下に設定ファイルを作成することで実現できます。なお設定ファイル名は `default` としておけば良いようです。

今回は [この記事](https://vm.gowatana.jp/entry/2021/01/19/022408) を参考に（というか丸パクリ、、）メニューが表示されるようにしています。

```bash:PXEブートの設定
cd /var/lib/tftpboot
sudo mkdir -p pxelinux.cfg
# viコマンドでdefaultファイルを作成（内容は別掲）
sudo vi pxelinux.cfg/default
# メニュー設定をpxe.confファイルとして作成（内容は別掲）
sudo vi pxelinux.cfg/pxe.conf
```

```:pxelinux.cfg/default
DEFAULT ::bios/vesamenu.c32
TIMEOUT 800
ONTIMEOUT 1
PROMPT 0
# メニューファイルの設定
MENU INCLUDE ::pxelinux.cfg/pxe.conf
NOESCAPE 1

# メニュー１　Memtest86+
LABEL memtest86
  MENU LABEL Memtest86+ 5.31
  KERNEL ::memtest/memtest86+-5.31b

# メニュー２　LinuxMintインストール起動（要編集：IPアドレス）
LABEL LinuxMint20
  MENU Linux Mint 20.2 MATE 64bit
  KERNEL ::mint20mate/casper/vmlinuz
  INITRD ::mint20mate/casper/initrd.lz
  APPEND boot=casper ip=dhcp root=/dev/nfs ro netboot=nfs nfsroot=<PXEサーバのIPアドレス>:/var/lib/tftpboot/mint20mate toram nosplash --
```

```:pxelinux.cfg/pxe.conf
MENU TITLE PXE Server
NOESCAPE 1
ALLOWOPTIONS 1
PROMPT 0
menu width 80
menu rows 14
MENU TABMSGROW 24
MENU MARGIN 10
menu color title 1;36;44 #ff008080 #00000000 std
```
:::note
さらっと書きましたが、この pxelinux.cfg/default の設定が今回の肝のひとつで、ディストリビューションおよびその世代によって起動の仕方が異なるので内容が異なる様です。他のディストリビューションなどには応用効かない箇所もあると思いますので注意してください。
:::

まだ設定が残っていますが、通常、この仮想マシンのネットワーク設定は **NAT** もしくは **ブリッジアダプター** のみの場合が多いと思いますので
一旦ネットワークの設定を変更するために仮想マシンをシャットダウンしてください。

## 【手順２】 ホストオンリーネットワークでの設定
VirtualBoxでの仮想マシンのネットワークのデフォルトは **NAT** です。
VirtualBoxのネットワークの解説は [この記事](https://qiita.com/feifo/items/0fde474005589afcff68) などが参考になると思いますが、今回はこの設定を切り替えることで、**ターゲットPCのような物理マシン**と**VirtualBox上に作成した試験用仮想マシン** 両方に対応できるようにします。

最終的な目標であるターゲットPCへのインストール時は以下のような構成になります。PXEサーバのネットワーク設定を **ブリッジアダプター** にすることでターゲットPCと同じLAN上に接続されることになります。
![Qiita記事用20210927-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/a424da3e-0456-1ad5-3f21-6c457c91cbf4.png)
その前段階として、試験用の仮想マシンとPXEサーバを **ホストオンリーアダプター** を介したネットワークで検証します。先の構成ではルータが担っていたDHCPサーバ機能はホストが行うので、PXEサーバ（dnsmasq）は同じProxyDHCP構成（**付与されるIPアドレスは異なるのに注意**）で運用することができます。
![Qiita記事用20210927-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/3d5eef29-b8c6-4a05-5d3b-d05e4e5e6656.png)


【手順１】の最後でPXEサーバの仮想マシンは電源オフの状態になっていると思いますので、VirtualBoxマネージャの設定からネットワークを選択し、**ホストオンリーアダプター**を割り当てて再起動してください。
![vitualbox_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/ab601c45-8f9a-4d14-870b-0cc960a83fe0.png)

---
再起動したらまずPXEサーバのIPアドレスを確認します。
UbuntuDesktopでしたら有線接続されている筈ですので設定メニューから確認ください。

:::note warn
このIPアドレスは一定ではありません。今回はネットワーク構成を変えますし
変更しなくてもDHCPのリース期間が経てば変わる場合があります。
PXEサーバを立ち上げる度に確認する方がいいでしょう。
:::

このIPアドレスが必要になるのは以下の設定です。

1. ProxyDHCPの設定: /etc/dnsmansq.d/pxe.conf （後で説明）
1. PXEサーバの設定: /var/lib/tftpboot/pxelinux.cfg/default （【手順１】で説明済）
1. NFSサーバの設定: /etc/exports　（後で説明）

２．の方ですが、**\<PXEサーバのIPアドレス>** がこの値になります。

また、dnsmasqの設定ファイルは `/etc/dnsmasq.conf` ですが
今回は１．の`/etc/dnsmasq.d/pxe.conf`を作成して`/etc/dnsmasq.conf`から読み込ませるようにします。
（dnsmasqをインストールした時点で`/etc/dnsmasq.d`フォルダは作成されている筈です）

ここで編集すべき、**\<ネットワークアドレス>**ですが、ここでは詳しい説明は省略します。
仮に、PXEサーバのIPアドレスが `192.168.56.101` ならば、
ネットワークアドレスは `192.168.56.0` でOKだと思います。

```:/etc/dnsmasq.d/pxe.conf
# DNSサーバとして機能させない設定
port=0

log-dhcp
 
# PXEリクエストに対してProxyDhcpとして応答する設定
# <ネットワークアドレス>は通常PXEサーバのIPアドレスの４オクテット目
# （"."で区切られた数字の４番目）を"0"にすればOK
dhcp-range=<ネットワークアドレス>,proxy 
 
# PXEブート時のイメージを指定
# UEFIのPCはこの設定では起動しないとのことだが未検証
pxe-service=x86PC,"PXE Boot",pxelinux
 
# pxelinux.0 の送信のため、TFTPサーバを起動
# 【手順１】のとおりファイルを置かないと失敗する
enable-tftp
tftp-root=/var/lib/tftpboot
```
`/etc/dnsmasq.d/pxe.conf`を読み込ませる為、`/etc/dnsmasq.conf`内の以下の行のコメントを外します。

```:/etc/dnsmasq.conf　（一部）
#conf-dir=/etc/dnsmasq.d/*.conf
```
dnsmasqはその名の通り本来はDNSサーバ機能を提供していますが、今回のようにDNS機能を殺す場合（pxe.conf内にport=0を設定）、名前解決にdnsmasqを利用しない様、`/etc/default/dnsmasq` の最後に以下の行を追加します。

```:/etc/default/dnsmasq　（最後に以下の行を追加）
DNSMASQ_EXCEPT=lo
```

あと３．のNFSサーバの設定ですが、`/etc/exports` に以下の行を追加して、ISOイメージをNFSを介して共有できるようにします。

```:/etc/exports　（最後に以下の行を追加）
/var/lib/tftpboot/mint20mate  <PXEサーバのIPアドレス>/255.255.255.0(ro,sync,no_subtree_check)
```
設定を反映するため、NFSサーバを再起動します。

```bash:NFSサーバの再起動
sudo systemctl restart nfs-kernel-server
```

---
これまで当然のように書いてきましたが、今回LinuxMintのISOイメージにあるファイル一式を`/var/lib/tftpboot/mint20mate` 配下にコピーします。
VirtualBoxの機能を使って、ISOイメージをマウントした場合、`/media/$USER/Linux Mint 20.2 MATE 64-bit` にマウントされると思いますので、以下のコマンドでコピーします。

```bash:ISOイメージのコピー
cd /var/tftpboot
sudo mkdir -p mint20mate
sudo cp -r /media/$USER/Linux\ Mint\ 20.2\ MATE\ 64-bit/. mint20mate
```

:::note
上記のなにげないファイルのコピーですが、ここでハマりました。
はじめは、cp -r 「コピー元のフォルダ」/* 「コピー先のフォルダ」としていたのですが、うまくいかず調べてみたところ、
ISOイメージのトップフォルダに、.disk という隠しフォルダがあり、それがコピーされていないのが原因でした。ご参考までに。
:::

長文になりましたが、PXEサーバの設定は以上になります。
最後にデバッグモードで dnsmasqを起動し、試験に臨みます。

```bash:デバッグモードでdnsmasqを起動
sudo dnsmasq -d
```

## 【手順３】 試験用仮想マシンでの起動試験
試験用に新たな仮想マシンをVirtualBoxで作成します。
ポイントは以下の２点だけです。あとはデフォルトで構わないと思います。
- 起動順序の**ネットワークにチェック**をいれて順序を最上位にする
- ネットワークアダプターを**ホストオンリーアダプター**にする
![vitualbox_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/16647290-c896-d9f5-ceae-150f77f53461.png)
![vitualbox_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/352987ea-e282-74e6-371b-3ab12498b0b0.png)
仮想マシンを起動したら、以下の様な画面が表示されると思います。
カーソルを下にして「Enter」を入力し、LinuxMintのLiveCD画面が表示されたら成功です。
![vitualbox_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2018569/db14e1b5-4203-31de-066d-6c674e5fe41b.png)

##おわりに
以上で説明を終わります。【手順４】本番環境での説明は省略します。
おおざっぱに書くと、PXEサーバのネットワークアダプタを変更し再起動後、IPアドレス関連を修正して、nfs-kernel-serverの再起動およびdnsmasqの起動を行うという手順になります。

ただし、`/etc/dnsmasq.d/pxe.conf`の**<ネットワークアドレス>の説明を簡略化**したことなどもあり、以下の注意喚起をさせてください。

:::note alert
今回の構成は、家庭内ネットワークなど限られたネットワーク内での実施を前提としています。
企業内ネットワークなど複雑な構成のネットワーク内での実施を想定していません。
個別にルータを準備してローカル環境内で実施するなどの配慮をお願いします。

本記事の手順を実施して、何か問題が起こっても当方は責任を負いかねます。
:::

以上です。最後までお読みいただき、ありがとうございました。