はじめに
通常の Nerves アプリ開発では、公式に用意されている Nerves System を利用できるので、mix.exs に対象機器用の依存関係を追加するだけでインストールが済みます。
しかしながら、やりたい内容によっては、Nerves System を自分でカスタマイズしてビルドしたくなります。
この記事では、Nerves Systems Builder を使って、sqlite3 命令を含むカスタム Nerves System を作ります。
SQLite は、最初のカスタム Nerves System 題材として扱いやすいです。特別な周辺機器を用意しなくても確認でき、Buildroot の package 追加と /data の永続化を小さく試せます。
今回の到達点は、Nerves System に sqlite3 を追加し、/data/demo.db に保存した内容が再起動後も残ることを確認するところまでです。
今回の例では、Raspberry Pi 5 向けの Nerves System に SQLite のコマンドラインツールを追加します。
同じ考え方は Raspberry Pi 4 など、他の対象機器にも応用できます。
全体像
Nerves System のビルド作業と、通常の Nerves アプリのビルド作業は分けて考えると理解しやすいです。
~/nerves_systems/
カスタム Linux / Nerves System をビルドする場所
~/Projects/my_nerves_app/
そのカスタム System を使って Elixir ファームウェアをビルドする場所
もう少し具体的には、次のような関係です。
+-------------------------+
| ~/nerves_systems |
| |
| src/nerves_system_rpi5 | 保存すべき System 側の変更
| o/rpi5 | Buildroot の生成物
+------------+------------+
|
| source o/rpi5/nerves-env.sh
v
+---------------------------+
| ~/Projects/my_nerves_app |
| |
| mix firmware | カスタム System を使ってビルド
+---------------------------+
重要なのは、o/rpi5 は生成物であり、長期的に残すべき変更は src/nerves_system_rpi5 側に保存するという点です。
主なディレクトリ
この記事では、次の構成を前提にします。
~/nerves_systems/
├── config/
│ └── config.exs
├── src/
│ └── nerves_system_rpi5/
└── o/
└── rpi5/
~/Projects/
└── my_nerves_app/
それぞれの意味は以下です。
config/config.exs
nerves_systems がどの System を clone / build するかを指定する
src/nerves_system_rpi5/
実際の Nerves System のソースコード
長期的に残す変更はここに保存し、コミットする
o/rpi5/
Buildroot の生成物
make menuconfig はここで実行する
必要に応じて削除して再生成できる
~/Projects/my_nerves_app/
通常の Nerves アプリ
SQLite 専用アプリである必要はない
Linux マシンを準備する
Nerves System のビルドには、ある程度の容量と時間が必要です。
目安として、次のような環境を用意します。
- CPU:
x86_64またはaarch64 - OS: Linux
- 空き容量: 128 GB 以上
Debian 系の Linux であれば、必要な package はおおむね次のように入れられます。
sudo apt update
sudo apt install \
git \
build-essential \
bc \
cmake \
cvs \
wget \
curl \
mercurial \
python3 \
python3-aiohttp \
python3-flake8 \
python3-ijson \
python3-nose2 \
python3-pexpect \
python3-pip \
python3-requests \
rsync \
subversion \
unzip \
gawk \
jq \
squashfs-tools \
libssl-dev \
automake \
autoconf \
libncurses5-dev
Erlang、Elixir、nerves_bootstrap については、通常の Nerves 開発環境と同じです。
mix local.hex
mix local.rebar
mix archive.install hex nerves_bootstrap
ここで入れるのは nerves_bootstrap アーカイブです。nerves package そのものではありません。
nerves_systems を clone する
ホームディレクトリ配下に nerves_systems を clone します。
cd ~
git clone https://github.com/nerves-project/nerves_systems.git
cd ~/nerves_systems
Raspberry Pi 5 だけをビルド対象にする
設定ファイルを作ります。
cp config/starter-config.exs config/config.exs
config/config.exs を編集して、Raspberry Pi 5 の System だけを残します。
[
systems: [
{:nerves_system_rpi5, "https://github.com/nerves-project/nerves_system_rpi5.git"}
]
]
Raspberry Pi 4 の場合は、たとえば次のようになります。
[
systems: [
{:nerves_system_rpi4, "https://github.com/nerves-project/nerves_system_rpi4.git"}
]
]
複数の System を同時に扱うこともできますが、最初は対象を一つに絞る方が分かりやすいです。
一度そのままビルドする
まず、何も変更せずに一度ビルドします。
cd ~/nerves_systems
mix deps.get
mix ns.clone
mix ns.build
完了すると、次のディレクトリができているはずです。
~/nerves_systems/src/nerves_system_rpi5/
~/nerves_systems/o/rpi5/
確認します。
ls ~/nerves_systems/src/nerves_system_rpi5
ls ~/nerves_systems/o/rpi5
カスタム用の branch を作る
生成物は o/rpi5 にありますが、保存すべき System のソースコードは src/nerves_system_rpi5 にあります。
まず、System 側のソースコードで branch を作ります。
cd ~/nerves_systems/src/nerves_system_rpi5
git switch -c custom-sqlite
最初の実験では fork しなくても大丈夫です。ローカル branch で十分です。
長期的に使う場合や、チームで共有する場合は、fork するか、自分たち用の System repository を用意するとよさそうです。
Buildroot の設定を変更する
SQLite は利用者空間の package なので、変更するのは Buildroot 側です。
生成物側のディレクトリで make menuconfig を開きます。
cd ~/nerves_systems/o/rpi5
make menuconfig
今回探すものは SQLite です。
sqlite
有効にしたい Buildroot の設定は次です。
BR2_PACKAGE_SQLITE=y
make menuconfig 上では、/ で検索して sqlite を探すのが早いです。
今回の環境では、SQLite は次の場所にありました。
Target packages
-> Libraries
-> Database
-> sqlite
実際の画面では、次のように sqlite を選択します。
Target packages
-> Libraries
-> Database
-> [*] sqlite
sqlite を選択すると、下に SQLite 関連の追加機能も表示されます。
[ ] Additional query optimizations (stat4)
[ ] Enable convenient access to meta-data about tables and queries
[ ] Enable version 3 of the full-text search engine
[ ] Enable the RTREE extension for SQLite
[ ] Enable sqlite3_unlock_notify() interface
[ ] Set the secure_delete pragma on by default
[ ] Disable fsync
最初の学習では、これらの追加機能は選ばず、sqlite 本体だけを有効にするのが分かりやすいです。
make menuconfig の基本操作は以下です。
矢印キー 移動
Enter 下位項目へ移動
Space 有効、無効の切り替え
Y 有効化
N 無効化
/ 検索
Esc Esc 戻る
Save 一時保存
Exit 終了
終了後、Buildroot の設定を System 側のソースコードへ保存します。
make savedefconfig
差分を確認します。
cd ~/nerves_systems/src/nerves_system_rpi5
git diff nerves_defconfig
期待する差分は、おおむね次のような内容です。
+BR2_PACKAGE_SQLITE=y
SQLite の追加機能を選んだ場合は、SQLite 関連の設定が他にも出ることがあります。
ただし、最初の学習では最小構成にしておく方が分かりやすいです。
Linux kernel の設定は変更しない
SQLite は通常のユーザー空間 package です。
そのため、この SQLite の実験では、通常は次を実行する必要はありません。
make linux-menuconfig
make linux-update-defconfig
今回変更するのは Buildroot の package 設定だけです。
SQLite:
Buildroot package 追加のみ
Linux kernel の defconfig 変更は不要です。
System 側の変更をコミットする
System 側の repository で差分を確認します。
cd ~/nerves_systems/src/nerves_system_rpi5
git status
git diff
問題なければコミットします。
git add nerves_defconfig
git commit -m "Add SQLite"
今回の最小構成では、意味のある変更は次だけです。
nerves_defconfig
BR2_PACKAGE_SQLITE=y
SQLite は利用者空間の package なので、linux-*.defconfig の変更は不要です。
カスタム System を再ビルドする
保存した設定をもとに、System を再ビルドします。
cd ~/nerves_systems
rm -rf o/rpi5
mix ns.build
学習中は、o/rpi5 を消してから再ビルドする方が分かりやすいです。
Buildroot の生成物が古い状態で残っていると、何が反映されているのか分かりにくくなるためです。
Nerves アプリからカスタム System を使う
ここからは通常の Nerves アプリ側の作業です。
新しい terminal を開いて、Nerves アプリのディレクトリへ移動します。
cd ~/Projects/my_nerves_app
先ほどビルドしたカスタム System の環境変数を読み込みます。
. ~/nerves_systems/o/rpi5/nerves-env.sh
export MIX_TARGET=rpi5
その後、通常通りファームウェアをビルドします。
mix deps.get
mix firmware
カスタム System が使われているか確認します。
mix nerves.info
次のように、system と toolchain が ~/nerves_systems/o/rpi5 を指していれば成功です。
system: /home/<user>/nerves_systems/o/rpi5
toolchain: /home/<user>/nerves_systems/o/rpi5/host
ファームウェアを書き込む
通常の Nerves の流れで書き込みます。
SD カードに書き込む場合は、たとえば次です。
mix burn
ネットワーク経由で更新する場合は、たとえば次です。
mix upload
使う命令は、対象機器やアプリの構成によって変わります。
SQLite を実機で確認する
ここからは Nerves IEx 上で確認します。
まず、sqlite3 が入っているか確認します。
cmd "type sqlite3"
期待する結果です。
sqlite3 is /usr/bin/sqlite3
/data に database を作る
Nerves では、通常の root filesystem は読み取り専用の System image として扱います。
永続化したい application data は /data に置きます。
今回は /data/demo.db を作ります。
まず table を作ります。
cmd """
sqlite3 /data/demo.db "create table if not exists events(message text, inserted_at text);"
"""
成功すると、終了 status として 0 が返ります。
0
行を追加します。
cmd """
sqlite3 /data/demo.db "insert into events values('hello from custom Nerves system', datetime('now'));"
"""
こちらも成功すると 0 が返ります。
0
読み返します。
cmd """
sqlite3 /data/demo.db "select rowid, message, inserted_at from events;"
"""
出力は次のような形になります。
1|hello from custom Nerves system|2026-06-02 11:24:58
0
最後の 0 は sqlite3 命令の終了 status です。
database file も確認します。
cmd "ls -lh /data/demo.db"
これで、対象機器上で sqlite3 が動いていることを確認できました。
再起動後も残ることを確認する
次に、/data が再起動後も残ることを確認します。
対象機器を再起動します。
Nerves.Runtime.reboot()
再接続後、もう一度同じ database を読みます。
cmd """
sqlite3 /data/demo.db "select rowid, message, inserted_at from events;"
"""
先ほど追加した行が表示されれば成功です。
![]()
![]()
![]()
おわりに
今回は、Nerves System に sqlite3 を追加し、/data/demo.db に保存した内容が再起動後も残ることを確認しました。
作業の流れは次の通りです。
- Buildroot で sqlite3 を入れる
- System 側に設定を保存する
- カスタム System で Nerves アプリをビルドする
- 実機で sqlite3 を実行する
- /data に保存した database が再起動後も残ることを確認する
SQLite は外部機器を用意せずに確認できるため、カスタム Nerves System の最初の題材として扱いやすいです。
小さな成功体験を作っておくと、Buildroot、System 設定、永続化領域の関係がかなり見通しやすくなります。
![]()
![]()
![]()




