OpenWrtのRaspberry Pi用イメージを作ってみた

2022.05.13

CX事業本部 IoT事業部のakkyです。今回は、ルーター用のLinuxディストリビューションであるOpenWrtのRaspberry Pi用イメージを作成してみたのでご紹介します。

OpenWrtの読み込み専用FSが簡単に使える点と、多様なハードウェアのサポートを試してみます。

OpenWrtについて

OpenWrtはルーター用の組み込み向けLinuxディストリビューションとして有名ですが、ルーター専用ハードウェアだけではなく、Raspberry PiやPINE A64などのSBCにも使用することができます。また、ルーターとしてだけでなく、独自にソフトウェアをインストールして、サーバとして使用することもできます。

OpenWrtは組み込み向けのため、イメージのサイズが小さく、ファイルシステムにSquashFSを選択できるため、ブートパーティションを読み込み専用に保護できることなどが特徴です。

公式サイトでは各種ハードウェア用のビルド済みイメージが公開されていますが、SBCに使用する際には、事前にインストールされているパッケージが少なかったり、パーティションのサイズが小さいことがすこし不便です。OpenWrtには Image Builderという仕組みがあり、カスタマイズしたイメージを簡単に作成することができますので、今回はこの仕組みを使って、事前にパッケージを組み込んだり、パーティションサイズを拡大したイメージを作ってみました。

作成の方針

  • 配布イメージは読み書きパーティションのサイズが104MBしかないため、サイズを拡大する
  • Pythonなどの使いそうなパッケージを事前に(SquashFSへ)組み込む
  • psコマンドをBusyBox組み込みのものから標準的なものに変える
  • ネットワークの設定を組み込む(IPアドレス等)

ImageBuilderによるイメージの作成

ImageBuilderを使用するために、WSL上のUbuntu 20.04を使用しました。まず、ビルドに必要なパッケージをインストールします。

$ sudo apt install build-essential libncurses5-dev libncursesw5-dev zlib1g-dev gawk git gettext libssl-dev xsltproc rsync wget unzip

次に、各ボード用のImage Builderをダウンロードします。公式配布のイメージと同じディレクトリにあります。今回はRaspberry Pi 1Bで使用するため、bcm2708用のImage Builderを使用します。

$ wget https://downloads.openwrt.org/releases/21.02.3/targets/bcm27xx/bcm2708/openwrt-imagebuilder-21.02.3-bcm27xx-bcm2708.Linux-x86_64.tar.xz
$ tar zxvf openwrt-imagebuilder-21.02.3-bcm27xx-bcm2708.Linux-x86_64.tar.xz
$ cd openwrt-imagebuilder-21.02.3-bcm27xx-bcm2708.Linux-x86_64

.configというファイルにOSの設定が書かれています。EXT4のジャーナリングの有効化、パーティションサイズの変更、BusyBoxのpsコマンドの無効化を行います。(変更点のみを示します)

CONFIG_TARGET_EXT4_JOURNAL=y
CONFIG_TARGET_KERNEL_PARTSIZE=128
CONFIG_TARGET_ROOTFS_PARTSIZE=4096
CONFIG_BUSYBOX_DDEFAULT_PS=n

次にネットワークの設定を変更します。Image Builderには作成されるイメージに含まれるファイルを任意のディレクトリの内容に上書きするオプションがあります。今回はImage Builderのディレクトリにfilesディレクトリを作成してコピー元とします。files/etc/config/networkファイルの中身は次のようにしました。

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config interface 'lan'
        option ifname 'eth0'
        option proto 'static'
        option netmask '255.255.255.0'
        option ipaddr '192.168.1.200'
        option gateway '192.168.1.1'
        option dns '192.168.1.1'

Image Builderのディレクトリに戻り、次のコマンドでビルドを行います。python3とpip、psコマンドを追加し、サーバには不要なpppとdhcpdを削除します。

$ make image PROFILE="rpi" PACKAGES="python3 python3-pip procps-ng-ps -ppp -ppp-mode-pppoe -odhcpd" FILES="files"

コマンドが完了すると、bin/targets/bcm27xx/bcm2708ディレクトリに完成したイメージが配置されています。カーネルなどはビルド済みなのでそれほど時間はかかりません。

squashfs版のファクトリーイメージであるopenwrt-21.02.3-bcm27xx-bcm2708-rpi-squashfs-factory.img.gzを解凍しSDカードに書き込みます。

Raspbianなどと同様にddコマンドを使用しますが、conv=fsync(または、OSによりconv=sync)オプションを必ず付けてください。squashfsのイメージはブロックサイズが中途半端なため、このオプションを付けないと起動時にカーネルパニックを起こしてしまいます。

$ gzip -d openwrt-21.02.3-bcm27xx-bcm2708-rpi-squashfs-factory.img.gz
$ sudo dd if=openwrt-21.02.3-bcm27xx-bcm2708-rpi-squashfs-factory.img of=<SDカードのデバイス名> bs=16m conv=fsync

SDカードをRaspberry Piに差し込んで、sshすると…動きました!ネットワークの設定もできていますね。

パーティションも広がり、Pythonもインストールされています。

おわりに

Image Builderを使ってOpenWrtのイメージを作成する方法をご紹介しました。 OpenWrtは対応ハードウェアも多く、組み込み向けに便利な設計ですので、IoT向けにも便利に使用できそうです。

参考資料