私でもできる！Raspberry Pi 3/4実機にVyOSインストール！！

:::note warn
ここで言う「私でもできる！」は筆者でもできるという意味であり、これを読んだ全ての人ができるという意味ではないので注意
:::

## やりたいこと

Raspberry Piの実機でVyOSを動かしたい

## 環境

### ビルド環境

- ThinkPad X1 YOGA 4gen
- NixOS 23.11
- Docker 20.10.25
- qemu v7.0.0

### 動作環境

- Raspberry Pi 3B
- Raspberry Pi 4B

### Git Commit Hash

|リポジトリ名     |commit hash     |
|---------------|----------------|
|vyos-pi-builder|`68044ec`       |
|vyos-build     |`142e877`       |
|linux          |`5a52cae54a05`  |
|linux-firmware |`d983107a`      |
|accell-ppp     |`9669bcb`       |
|ovpn-dco       |`dba96d2`       |

## やったこと

### 事前準備

Docker buildxでqemuを使ってARM64をエミュレーションできるようにする

```sh
docker run --privileged --rm tonistiigi/binfmt --install all
```

### VyOSのビルド

ここの手順は[私でもできる！M2MacBookでarm 64版VyOSコンテナ作成](https://qiita.com/yanbaru/items/c2b828a556d23f8da25e)を参考に進める

#### 事前準備

[vyos-pi-builder](https://github.com/runborg/vyos-pi-builder)をcloneする
vyos-pi-builderのREADMEに書いてあるとおりに実行してもうまく行かなかった(うまく行ってたらこんな記事書いてない)

```sh
git clone https://github.com/runborg/vyos-pi-builder
cd vyos-pi-builder
```

[vyos-build](http://github.com/vyos/vyos-build)をcloneする

```sh
git clone http://github.com/vyos/vyos-build
```

#### Raspberry Pi向けのLinux Kernelをビルド

[Raspberry Pi向けのLinux Kernel](https://github.com/raspberrypi/linux)をcloneする
kernelのソースコードはバカみたいにデカくて時間がかかるのでコーヒーでも飲みながら待つ

```sh
cd ./vyos-build/packages/linux-kernel/
git clone https://github.com/raspberrypi/linux
```
VyOSの設定をコピーする

```sh
cp linux/arch/arm64/configs/bcm2711_defconfig arch/arm64/configs/vyos_defconfig
```

Raspberry Pi用にパッチを当てる

pi-builderの`patches`ディレクトリにあるパッチを編集しないとパッチに失敗するので以下のコマンドでパッチファイルにパッチを当てます(何を言っているのかわからない)

```sh
patch -t -u ../../../patches/0001_bcm2711_defconfig.patch << EOF
diff --git a/patches/0001_bcm2711_defconfig.patch b/patches/0001_bcm2711_defconfig.patch
index 8da100c..624b404 100644
--- a/patches/0001_bcm2711_defconfig.patch
+++ b/patches/0001_bcm2711_defconfig.patch
@@ -225,14 +225,14 @@ index 30ceaf594..a732017a2 100644
  CONFIG_NET_SCH_CHOKE=m
  CONFIG_NET_SCH_QFQ=m
  CONFIG_NET_SCH_CODEL=m
-@@ -379,12 +429,15 @@ CONFIG_NET_CLS_BASIC=m
+@@ -380,10 +430,15 @@ CONFIG_NET_CLS_BASIC=m
  CONFIG_NET_CLS_ROUTE4=m
  CONFIG_NET_CLS_FW=m
  CONFIG_NET_CLS_U32=m
 +CONFIG_CLS_U32_PERF=y
  CONFIG_CLS_U32_MARK=y
- CONFIG_NET_CLS_RSVP=m
- CONFIG_NET_CLS_RSVP6=m
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
  CONFIG_NET_CLS_FLOW=m
  CONFIG_NET_CLS_CGROUP=m
  CONFIG_NET_CLS_BPF=y
EOF
```

その後パッチを当てます

```sh
patch -t -u arch/arm64/configs/vyos_defconfig < ../../../patches/0001_bcm2711_defconfig.patch
```

Kernelをビルドする
qemu上でKernelのビルドをするとアホみたいに時間がかかるのでコーヒーでも飲みながら待つ

```sh
docker run --rm -it --privileged -v $(pwd):/vyos -w /vyos vyos/vyos-build:current-arm64 bash
sudo ./build-kernel.sh
```

ビルドが終わると`linux-image-6.1.58-arm64-vyos_6.1.58-1_arm64.deb`のようなdebパッケージができるので、ファイル名からLinux Kernelのバージョンを取得する
今回は`6.1.58`だった

Linux firmwareのcloneとビルドを行なう
これもそこそこ長いのでコーヒーでも飲みながら待つ

```sh
git clone https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware
sudo ./build-linux-firmware.sh
```

accel-pppのcloneとビルドを行なう

```sh
git clone https://github.com/accel-ppp/accel-ppp
sudo ./build-accel-ppp.sh
```

openvpn-dcoのcloneとビルドを行なう

```sh
git clone https://github.com/OpenVPN/ovpn-dco
sudo ./build-openvpn-dco.sh
```

一旦コンテナから出る

```sh
exit
```

ここでビルドした各種`*.deb`は`packages`ディレクトリの直下に配置しておく

#### VyOSのISOビルド

`vyos-pi-builder/vyos-build/data/architectures/arm64.toml`を以下のように変更する

```toml:vyos-pi-builder/vyos-build/data/architectures/arm64.toml
additional_repositories = [
  "deb [arch=arm64] https://repo.saltproject.io/py3/debian/11/arm64/3005 bullseye main"
]

kernel_flavor = "arm64-vyos"

packages = ["vyos-linux-firmware", "telegraf", "grub-efi-arm64", "openvpn-dco"]
bootloaders = "grub-efi"
```

依存パッケージである`teregraf`のarm64版のパッケージをダウンロードして、`vyos-pi-builder/vyos-build/packages`内に入れる
ここでは記事執筆活動での最新版である`1.28.2`を入れる

```sh
cd ../
curl -OL https://dl.influxdata.com/telegraf/releases/telegraf_1.28.2-1_arm64.deb
```

pi-builderのリポジトリルートに戻ってVyOSの初期設定を入れる

```sh
cd ../..
cp config.boot.default vyos-build/data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default
```

VyOSのISOイメージをビルドする
そこそこ長いのでコーヒーでも飲みながら待つ

```sh
cd vyos-build
docker run --rm -it --privileged -v $(pwd):/vyos -w /vyos vyos/vyos-build:current-arm64 bash
sudo ./build-vyos-image iso --architecture arm64 --build-by "cffnpwr [cffnpwr@gmail.com]"
```

ビルドが終わったらコンテナから出る

```sh
exit
```

`vyos-pi-builder/vyos-build/build`内にビルドされた`*.iso`のファイルが存在するのが確認できる

### u-bootのビルド

pi-builderのリポジトリルートにu-bootのclone

```sh
cd ..
git clone --depth=1 git://git.denx.de/u-boot
cd u-boot
```

u-bootの設定をする

```sh
docker run --rm -it --privileged -v $(pwd):/vyos -w /vyos vyos/vyos-build:current-arm64 bash
make rpi_3_defconfig
```

Pi4Bの場合は`make rpi_4_defconfig`を実行する
他のバージョンのRaspberry Piを使用する場合は`u-boot/configs`内から適切な設定ファイル名を選ぶ

u-bootのビルドをする

```sh
sudo make -j $(getconf _NPROCESSORS_ONLN)
```

ビルドが終了したらコンテナから出る

```sh
exit
```

### Raspberry Pi用イメージのビルド

pi-builderのスクリプトを使ってビルドします
ここでDockerコンテナに`/dev`をマウントするのが肝で、これがないとループバックマウントに失敗する

```sh
cd ..
docker run --rm -it --privileged -v $(pwd):/vyos -v /dev:/dev -w /vyos vyos/vyos-build:current-arm64 bash
sudo DEVTREE="bcm2710-rpi-3-b" PIVERSION=3 UBOOTBIN=u-boot/u-boot.bin ./build-pi-image.sh vyos-build/build/live-image-arm64.hybrid.iso
```

Raspberry Pi4の場合は最後のコマンドを以下に置き換える

```sh
sudo DEVTREE="bcm2711-rpi-4-b" PIVERSION=4 UBOOTBIN=u-boot/u-boot.bin ./build-pi-image.sh vyos-build/build/live-image-arm64.hybrid.iso
```

ビルドが終了したらコンテナから出る

```sh
exit
```

### 動作確認

pi-builderのリポジトリルートに`vyos-bcm2710-rpi-3-b.img`のような名前の`*.img`ファイルが存在するのでこれを適当なSDカードに焼く
(Raspberry Pi4の場合は`vyos-bcm2711-rpi-4-b.img`になっているはず)

実際にRaspberry Pi実機に挿して起動してみて起動したら成功


### 余談

Raspberry Pi 3BではEFIパーティション内の`config.txt`から`dtoverlay=disable-bt`を削除しないと虹色の画面から起動しなかった
UARTで確認してもu-bootのログが流れてこなかったので`start.elf`でコケてるのだと思われる

## 参考文献とか

- [私でもできる！M2MacBookでarm 64版VyOSコンテナ作成](https://qiita.com/yanbaru/items/c2b828a556d23f8da25e)
- [Raspberry Pi 4 Model B 上で VyOS を動かす](https://qiita.com/DJ_Kaosun/items/6fc072e8490725e6c037)
- [vyos-pi-builder](https://github.com/runborg/vyos-pi-builder)
- [vyos-build](https://github.com/vyos/vyos-build)