Raspberry Pi 4 Model B 上で VyOS を動かす

# 2023/01/02 追記
~~[GitHub でフォークして](https://github.com/djkaosun/vyos-pi-builder/tree/kernel_build)、とりあえず動くようにしてみた。~~

# 2023/01/03 追記
プルリクが通って、この記事の分は [vyos-pi-builder](https://github.com/runborg/vyos-pi-builder "GitHub:runborg/vyos-pi-builder") に反映された。この記事みたいなことをやらなくても動くようになってるはず。

# はじめに

[vyos-pi-builder](https://github.com/runborg/vyos-pi-builder "GitHub:runborg/vyos-pi-builder") ってのを見つけて「おーこんなのあるんだ、なら簡単にできるやろ。」と思ったが、うまく動かないというorz (2022/12/20 現在)

カーネルのビルドとか初体験だし、有識者から見ると「なんでそんなことしてるの？」ってところが多々あると思います。私の知識向上のため、ぜひご指導ご鞭撻のほどお願いいたします！

# ubuntu と docker の準備

さほど縛りはなかろうが、私が作業した環境はこんな感じ。

```text:ubuntu
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```
```text:docker-ce
Package: docker-ce
Version: 5:20.10.22~3-0~ubuntu-jammy
Priority: optional
Section: admin
Maintainer: Docker <support@docker.com>
Installed-Size: 88.5 MB
Depends: containerd.io (>= 1.4.1), docker-ce-cli, iptables, libseccomp2 (>= 2.3.0), libc6 (>= 2.34), libdevmapper1.02.1 (>= 2:1.02.97), libsystemd0
Recommends: apparmor, ca-certificates, docker-ce-rootless-extras, git, libltdl7, pigz, procps, xz-utils
Suggests: aufs-tools, cgroupfs-mount | cgroup-lite
Conflicts: docker (<< 1.5~), docker-engine, docker-engine-cs, docker.io, lxc-docker, lxc-docker-virtual-package
Replaces: docker-engine
Homepage: https://www.docker.com
Download-Size: 20.5 MB
APT-Manual-Installed: yes
APT-Sources: https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages
Description: Docker: the open-source application container engine
 Docker is a product for you to build, ship and run any application as a
 lightweight container
 .
 Docker containers are both hardware-agnostic and platform-agnostic. This means
 they can run anywhere, from your laptop to the largest cloud compute instance and
 everything in between - and they don't require you to use a particular
 language, framework or packaging system. That makes them great building blocks
 for deploying and scaling web apps, databases, and backend services without
 depending on a particular stack or provider.
```

```text:qemu-user-static
Package: qemu-user-static
Version: 1:6.2+dfsg-2ubuntu6.6
Built-Using: gcc-12 (= 12.1.0-2ubuntu1~22.04), glib2.0 (= 2.72.1-1), glibc (= 2.35-0ubuntu3), gnutls28 (= 3.7.3-4ubuntu1.1), liburing (= 2.1-2build1), zlib (= 1:1.2.11.dfsg-2ubuntu9.2)
Priority: optional
Section: universe/otherosfs
Source: qemu
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian QEMU Team <pkg-qemu-devel@lists.alioth.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 130 MB
Provides: qemu-user-binfmt
Recommends: binfmt-support
Suggests: sudo
Conflicts: qemu-user-binfmt
Breaks: binfmt-support (<< 2.1.7~)
Homepage: http://www.qemu.org/
Download-Size: 13.0 MB
APT-Manual-Installed: yes
APT-Sources: http://jp.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages
Description: QEMU user mode emulation binaries (static version)
 QEMU is a fast processor emulator: currently the package supports
 ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
 SPARC and x86-64 emulation. By using dynamic translation it achieves
 reasonable speed while being easy to port on new host CPUs.
 .
 This package provides the user mode emulation binaries, built
 statically. In this mode QEMU can launch Linux processes compiled for
 one CPU on another CPU.
 .
 qemu-user-static package will register binary formats which the provided
 emulators can handle, so that it will be possible to run foreign binaries
 directly.
```

# リポジトリのクローン

まず、vyos-pi-builder と [vyos-build](https://github.com/vyos/vyos-build "GitHub:vyos/vyos-build") リポジトリをクローンする。すべてはここから始まる。
```bash:コマンド
git clone https://github.com/runborg/vyos-pi-builder
cd vyos-pi-builder
git clone -b current --single-branch https://github.com/vyos/vyos-build
cd ..
```

# 各ファイルの変更 (vyos-pi-builder 関連)

そして、おもむろに `vyos-pi-builder/Makefile` を書き換える。元のままだと docker のオプションが古いのか、うまく動かない。

あと、カーネルもビルドしなきゃならんので、それ用の記述も増やす。

Makefile のインデントはタブ。
```diff:vyos-pi-builder/Makefile
  container:
- 	sudo rm -rf vyos-build
- 	git clone -b current --single-branch https://github.com/vyos/vyos-build
- 	sudo docker build --arch arm64 vyos-build/docker -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static -t vyos/vyos-build:current-arm64
+ 	sudo docker build --platform arm64 vyos-build/docker -t vyos/vyos-build:current-arm64
 
+ pi-kernel:
+ 	sudo docker run --rm -it --platform arm64 --privileged -v "$(shell pwd)":/vyos -v /dev:/dev --sysctl net.ipv6.conf.lo.disable_ipv6=0 vyos/vyos-build:current-arm64 /bin/bash -c 'cd /vyos; /bin/bash -x build-pi-kernel.sh'
 
- iso-local:
- 	sudo docker run --rm -it --arch arm64 --privileged -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static -v "$(shell pwd)":/vyos -v /dev:/dev --sysctl net.ipv6.conf.lo.disable_ipv6=0 localhost/vyos/vyos-build:current-arm64 /bin/bash -c 'cd /vyos; /bin/bash -x build-image.sh'
  
  iso-registry:
- 	sudo docker run --rm -it --arch arm64 --privileged -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static -v "$(shell pwd)":/vyos -v /dev:/dev --sysctl net.ipv6.conf.lo.disable_ipv6=0 vyos/vyos-build:current-arm64 /bin/bash -c 'cd /vyos; /bin/bash -x build-image.sh'
+ 	sudo docker run --rm -it --platform arm64 --privileged -v "$(shell pwd)":/vyos -v /dev:/dev --sysctl net.ipv6.conf.lo.disable_ipv6=0 vyos/vyos-build:current-arm64 /bin/bash -c 'cd /vyos; /bin/bash -x build-image.sh'
```
で、カーネル ビルド用のスクリプトを作る。
```bash:コマンド
touch vyos-pi-builder/build-pi-kernel.sh
chmod 775 vyos-pi-builder/build-pi-kernel.sh
vi vyos-pi-builder/build-pi-kernel.sh
```
```bash:vyos-pi-builer/build-pi-kernel.sh
set -x
set -e
ROOTDIR=$(pwd)
cd vyos-build/packages/linux-kernel/
git clone https://github.com/raspberrypi/linux
./build-kernel.sh
git clone https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
#ln -s linux/drivers/firmware linux-firmware
./build-linux-firmware.sh
git clone https://github.com/accel-ppp/accel-ppp.git
./build-accel-ppp.sh
```
`vyos-pi-builder/build-image.sh` も弄っていく。まず、せっかく変更した vyos-build 内のファイルを削除されると泣くので、そこを削除。

あと、[最近 vyos-build のフレーバー システムが変わった](https://phabricator.vyos.net/T3664) (というか現在進行形で変更中？) らしく、そこもなんとかする。ビルド フレーバーの指定方法がよく判らんかったから、無理矢理感がハンパない。

```diff_shell:vyos-pi-builder/build-image.sh
# (前略)

  # Clean out the build-repo and copy all custom packages
- rm -rf vyos-build
- git clone http://github.com/vyos/vyos-build vyos-build
  for a in $(find build -type f -name "*.deb" | grep -v -e "-dbgsym_" -e "libnetfilter-conntrack3-dbg"); do
  	echo "Copying package: $a"
  	cp $a vyos-build/packages/
  done
  
  cd vyos-build
  
  echo "Copy new default configuration to the vyos image"
  cp ${ROOTDIR}/config.boot.default data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default
  
  # Build the image
- VYOS_BUILD_FLAVOR=data/generic-arm64.json
- ./configure
- make iso
+ /vyos/vyos-build/build-vyos-image iso --architecture arm64
  
  cd $ROOTDIR
  
  # Build u-boot
  bash build-u-boot.sh

# (後略)
```

# 各ファイルの変更 (vyos-build 関連)

VyOS の中で [telegraf](https://www.influxdata.com/time-series-platform/telegraf/ "influx:telegraf") とかいうパッケージを使ってるらしく、live-build の処理の途中でインストールが走る。ので、所定の場所にパッケージ リポジトリの GPG 鍵を置く。
```bash:コマンド
wget -qO- https://repos.influxdata.com/influxdb.key > vyos-pi-builder/vyos-build/data/live-build-config/archives/influxdb.key.chroot
```
vyos-build で用意されている arm64.toml もいろいろ足りないから追加する。

```diff_toml:vyos-pi-builder/vyos-build/data/architectures/arm64.toml
+ additional_repositories = [
+   "deb [arch=arm64] https://repos.influxdata.com/debian bullseye stable"
+ ]
+ 
+ kernel_flavor = "arm64-vyos"
+ 
  # Packages added to images for x86 by default
  packages = [
+   "vyos-linux-firmware",
+   "telegraf",
    "grub-efi-arm64"
  ]
  bootloaders = "grub-efi"
```

カーネルのバージョンによくわからん「-v8」が付くから、無理やり動かすためにスクリプトをちょっと変える。(美しいとか関係なく、とにかく動かす！)

```diff:vyos-pi-builder/vyos-build/build-vyos-image
- --linux-packages linux-image-{{kernel_version}} \
+ --linux-packages linux-image-{{kernel_version}}-v8 \
```

```diff:vyos-pi-builder/vyos-build/packages/linux-kernel/build-linux-firmware.sh
- FW_FILES=$(find ${LINUX_SRC}/debian/linux-image/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/kernel/drivers/net -name *.ko | xargs modinfo | grep "^firmware:" | awk '{print $2}')
+ FW_FILES=$(find ${LINUX_SRC}/debian/linux-image/lib/modules/${KERNEL_VERSION}-v8${KERNEL_SUFFIX}/kernel/drivers
```

# ビルドしてみる

各 make で、それぞれ 1 ～ 2 時間かかる…。

まずは Docker コンテナ。
```bash:コマンド
cd vyos-pi-builder
make container
```
次に、カーネル。
```bash:コマンド
make pi-kernel
```
そしてついに、VyOS。
```bash:コマンド
make iso-registry
```

# Raspberry Pi Imager で焼き焼き & いざ起動
`vyos-pi-builder/vyos-bcm2711-rpi-4-b.img` を microSD に焼く。


# Wi-Fi を使えるようにする (VyOS 上での対処)

やっと動いた VyOS だが、Wi-Fi が使えない…。有線 LAN でインターネットに接続できるようにして、足りないファイルを持ってくる。本当はイメージ作成の段階で入れたほうがキレイなんだろうが、もういいでしょ…。

```bash:コマンド
sudo -i
vi /etc/apt/sources.list
```
```text:/etc/apt/sources.list
deb http://ftp.de.debian.org/debian bullseye main non-free-firmware
```

```bash:コマンド
apt update
apt install firmware-brcm80211
vi /lib/firmware/brcm/brcmfmac43455-sdio.txt
modprobe -r brcmfmac
modprobe brcmfmac
```
ファイルの内容は以下。
<details><summary>/lib/firmware/brcm/brcmfmac43455-sdio.txt</summary><div>

```text
# Cloned from bcm94345wlpagb_p2xx.txt 
NVRAMRev=$Rev: 498373 $
sromrev=11
vendid=0x14e4
devid=0x43ab
manfid=0x2d0
prodid=0x06e4
#macaddr=00:90:4c:c5:12:38
nocrc=1
boardtype=0x6e4
boardrev=0x1304

#XTAL 37.4MHz
xtalfreq=37400

btc_mode=1
#------------------------------------------------------
#boardflags: 5GHz eTR switch by default
#            2.4GHz eTR switch by default
#            bit1 for btcoex
boardflags=0x00480201
boardflags2=0x40800000
boardflags3=0x44200100
phycal_tempdelta=15
rxchain=1
txchain=1
aa2g=1
aa5g=1
tssipos5g=1
tssipos2g=1
femctrl=0
AvVmid_c0=0,157,1,126,1,126,1,126,1,126
pa2ga0=-170,5896,-680
pa2ga1=-156,4032,-547
pa5ga0=-150,5547,-628,-150,5583,-640,-158,5608,-649,-160,5757,-673
pa5ga1=-109,3831,-519,-88,3821,-512,-125,3731,-528,-103,3829,-516
itrsw=1
pdoffsetcckma0=2
pdoffset2gperchan=0,-2,1,0,1,0,1,1,1,0,0,-1,-1,0
pdoffset2g40ma0=16
pdoffset40ma0=0x8888
pdoffset80ma0=0x8888
extpagain5g=2
extpagain2g=2
tworangetssi2g=1
tworangetssi5g=1
# LTECX flags
# WCI2
ltecxmux=0
ltecxpadnum=0x0504
ltecxfnsel=0x22
ltecxgcigpio=0x32

maxp2ga0=80
ofdmlrbw202gpo=0x0022
dot11agofdmhrbw202gpo=0x4442
mcsbw202gpo=0x98444422
mcsbw402gpo=0x98444422
maxp5ga0=82,82,82,82
mcsbw205glpo=0xb9555000
mcsbw205gmpo=0xb9555000
mcsbw205ghpo=0xb9555000
mcsbw405glpo=0xb9555000
mcsbw405gmpo=0xb9555000
mcsbw405ghpo=0xb9555000
mcsbw805glpo=0xb9555000
mcsbw805gmpo=0xb9555000
mcsbw805ghpo=0xb9555000

swctrlmap_2g=0x00000000,0x00000000,0x00000000,0x010000,0x3ff
swctrlmap_5g=0x00100010,0x00200020,0x00200020,0x010000,0x3fe
swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x3
swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x3

vcodivmode=1
deadman_to=481500000

ed_thresh2g=-54
ed_thresh5g=-54
eu_edthresh2g=-54
eu_edthresh5g=-54
ldo1=4
rawtempsense=0x1ff
cckPwrIdxCorr=3
cckTssiDelay=150
ofdmTssiDelay=150
txpwr2gAdcScale=1
txpwr5gAdcScale=1
dot11b_opts=0x3aa85
cbfilttype=1
fdsslevel_ch11=6

# Improved Bluetooth coexistence parameters from Cypress
btc_mode=1
btc_params8=0x4e20
btc_params1=0x7530
```
</div></details>

# おまけ: ShellInABox を入れる
ここまでで VyOS on Raspberry Pi は動くようになる。あとはおまけ。VyOS に [ShellInABox](https://github.com/shellinabox/shellinabox/blob/master/README.md "ShellInABox") を入れてみる。

```bash:コマンド
sudo -i
vi /etc/apt/sources.list
```
```text:/etc/apt/sources.list
deb http://ftp.de.debian.org/debian bullseye main 
```
```bash:コマンド
apt update
apt install shellinabox
```
まぁなんというか、ふつー。でも、VyOS にパッケージを簡単に追加できるって知らなかったから、「おー！」って感じでした。

# おまけ 2: iPhone で USB テザリング

ついでに、iPhone の USB テザリング用のパッケージでも入れておくか。使うかはわからんが。
```bash:コマンド
apt install ipheth-utils libimobiledevice-utils usbmuxd
```
ってやって一旦シャットダウン後、iPhone を USB-A - Lightning ケーブルで繋げて電源 ON した。そうすると、iPhone が eth0 として一旦認識された後、eth1 に代わるという動きをした。

そのせいか、オンボードのネットワーク インターフェイスが見えなくなってしまった。(eth1 の iPhone しかない)

オンボードを元々 eth1 にすれば、iPhone は eth0 で安定してくれるだろうとの憶測から、それをやってみる。

最近の他の Linux ディストリビューションと同様に、udev の設定を弄る。
設定には MAC アドレスが必要。`00:90:4c:c5:12:37` は仮の値なので、自分のデバイスの MAC アドレスを書く。

```bash:コマンド
sudo -i
vi /etc/udev/rules.d/70-persistent-net.rules
```
```text:/etc/udev/rules.d/70-persistent-net.rules
# eth1
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:90:4c:c5:12:37", ATTR{type}=="1", NAME="eth1"
```
この後、再起動して無事に eth0 (iPhone) と eth1 (オンボード) が見えるようになった。

```text:コマンド
show interfaces
```
```text:show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
eth0             -                                 u/u  
eth1             -                                 u/D  
lo               127.0.0.1/8                       u/u  
                 ::1/128                                
wlan0            -                                 u/D  
```

なお、もともと eth0 で設定していたオンボード LAN の設定は飛ぶので、作業前に控えておく必要がある。まぁ以下のコマンドの結果を取っておけば OK。
```text:コマンド
show configuration commands
```

おわり。あとは、[これを持ち歩いて使ってみる](https://qiita.com/DJ_Kaosun/items/838a8c97c26c6a590b36)。