0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Raspberry Pi OS Liteをヘッドレスでインストールする(bookworm対応)

Last updated at Posted at 2024-09-16

 EWI-USB用の音源をRaspberry Pi 3A+で作ろうと思って、Raspberry Pi OS Liteをできるだけ軽く動くようにヘッドレスで設定をした記録です。以前はbullseyeでやってたんですが、使いたいシンセサイザーエンジンがbookwormを必要とし始めたので、やり直しました。bullseyeまでとずいぶん勝手が違いますね。

OSイメージの書き込み

 2022年春以降、Raspberry Pi OSのイメージファイルからデフォルトユーザが削除されました。その分、Raspberry Pi Imager(https://www.raspberrypi.com/software/ から入手、以下RPiImager)の機能が拡充され、ユーザの設定だけでなくSSHやWi-Fiおよび使用国、ロケールを詳細設定(右下の歯車マーク)からあらかじめ指定してmicroSDに書き込めるようになっているので、これを利用するのが一番良い選択だと思います。

 RPiImagerのバージョンには注意してください。Windows環境ではダウンロードしたインストーラを素直に起動すれば最新版がインストールされますが、筆者の母艦(Ubuntu 22.04.4 LTS)では、公式ページからダウンロードしたdebファイルを開いても、ページで案内されているsudo apt install rpi-imagerを実行しても、インストールされたのはリポジトリに登録されていた1.7.2に留まっていました。
 1.7.2で提供されるfirstrun.shではWi-Fiの設定がdhcpd前提のままで、bookwormで標準化されているNetworkManagerの設定ができません。「bookwormではヘッドレス設定はできないらしい」と解説しているページもあったのは、このせいかも。
 あれこれ調べて結局、最新版(執筆時点でバージョン1.8.5)をインストールする方法は

sudo snap install rpi-imager

でした。困っている方はお試しを。

 RPiImagerではOS が選べますが、今回は「Raspberry Pi OS(other)」を選んで出てくる64ビットLiteをRPi3A+で利用しました。Zeroや2以前は32ビットOSしか使えませんが、手順としては同様です。
Screenshot from 2024-08-18 15-48-33.png
 ユーザー設定、Wi-fiの設定、使用国と言語、SSHの有効化を設定して、書き込みへ進みましょう。

起動前に設定できることはやっておきたい

Wi-FiのIPアドレスを固定したい

 DHCPでIPアドレスをもらってくる時間を端折りたかったので、固定しました。
 RPiImagerは詳細設定をbootfsにあるfirstrun.shに書き込み、初回起動時に実行することで各種設定を進めていくので、事前にこのファイルへ埋め込んでしまいます。
 下から3行目に

firstrun.sh
rm -f /boot/firstrun.sh

とあるので、この前に追加しました。たぶん最終行exit 0の前ならいいんだと思いますが、実行される前にスクリプトが削除されるのが気持ち悪いのでここにしています。

 アドレス固定、DNSはGoogleパブリック、使う気がないIPv6は無効化、の設定を追記します。

systemctl start NetworkManager.service
nmcli connection reload
nmcli connection modify preconfigured ipv4.method "manual" ipv4.addresses "192.168.xx.yy/24" ipv4.gateway "192.168.xx.zz"
nmcli connection modify preconfigured ipv4.dns 8.8.8.8
nmcli connection modify preconfigured ipv6.method disabled
nmcli connection down preconfigured
nmcli connection up preconfigured

 preconfiguredは初回起動時の処理の中で作られるWi-Fiコネクションの識別子です。NetworkManagerがどのタイミングで起動しているか判別できなかったので、サービスを起動→コネクションの読み直し→アドレス固定、DNS設定、IPv6無効化→コネクション落として上げなおし、という手順にしています。
 念のため記しておくと、192.168.xx.yyが固定したいアドレス、192.168.xx.zzがゲートウェイのアドレスです。お手許の環境に合わせて書き換えてください。8.8.8.8はGoogleパブリックDNSのアドレスです。

DNSをGoogleパブリックにしていると、せっかくRPiImagerでホスト名を付けてもDNSに登録されないので、後の作業でホスト名でのアクセスができません。ルータがDNSを提供しているなら、DNSのアドレスはルータのアドレスにします。

https://netlog.jpn.org/r271-635/2024/04/raspberrypi_install_ver_bookworm.html
 こちらのページではfirstrun.shが何をやっているかを詳細に見ておられていて大変興味深いのですが、このバージョンではfirstrun.shが途中で呼び出すimager_customで一発モノのデーモンを作って、再起動後にそれが動いてpreconfiguredを作っています。先述のRPiImager1.7.2ではこのような動作がなくwpa_supplicant.confを作るのみでした。今回使った1.8.5では動作がまた変更されていて、imager_custompreconfigured.nmconnectionを直接作っています。そのため本稿ではこのようにしていますが、RPiImagerのバージョンが変わったらまたやり方を変えなければいけないかもしれません。

config.txtの設定

 bootfsにあるconfig.txtは、初回起動時に/boot/firmware/cmdline.txtにコピーされます。ここで編集しておくと便利です。
 [all]の下に追加していきます。以下は筆者の好みです。

config.txt
# メモリの割り当て変更:デフォルトではGPUに64MB振られているのを最低の16MBに
gpu_mem=16
# 動作クロックをターボモードに 
force_turbo=1
# Bluetooth無効
dtoverlay=disable-bt
# 電源LEDはデフォルトではパワーLEDは稼働時もシャットダウン後も点灯したままなので
# 点滅させて稼働中なのがわかるように
dtparam=pwr_led_trigger=heartbeat

 bootfsにあるcmdline.txtも、config.txt同様に初回起動時に/boot/firmware/cmdline.txtにコピーされます。
 以前のOSでは「cmdline.txtquietを追加して起動時のメッセージを抑制、起動時間を稼ぐ」というのをやっていましたが、今回のOSイメージではcmdline.txtにもともとquietって書かれてたので編集していません。他に指定するような設定があるなら、ここで先に設定しておくのは有用だと思います。

起動後に行う設定

 bootfsに配置されている設定ファイルは先にいじることができますが、rootfsにあるファイルは権限が設定されていたりシステムで書き換えられたりするので、起動後に設定することになります。
 準備したmicroSDをRPiにセット、起動したら、RPiImagerの詳細設定でつけたホスト名もしくは固定したIPアドレスにSSHでアクセスし、最初の設定を進めていきます。

 IPアドレスをDHCPから得ている場合、DHCPの払い出しログなどでRPiのMACアドレスB8:27:EB:〜DC:A6:32:〜E4:5F:01:〜のいずれかに対応するIPアドレスを探します。

パッケージの更新

 この後でテンポラリフォルダのRAMディスク化をしてしまうとうまくいかなくなることがあるので、先にやってしまいましょう。
 aptupgradeでいいかdist-upgradeまでやるかは状況によると思います。

command
sudo apt update
sudo apt -y upgrade
sudo apt -y dist-upgrade
sudo rpi-update

起動スピードを稼ぐ

 ちょっとだけでもと思ってやっています。

必要なさそうなサービスの停止

 firstrun.shに書き込んで先にやってしまうのを試してみたんですが、うまくいかなかったので起動後に。

command
sudo systemctl disable avahi-daemon
sudo systemctl disable systemd-timesyncd
sudo systemctl disable bluetooth
sudo systemctl disable hciuart
sudo systemctl disable ModemManager
sudo systemctl disable rsync
sudo systemctl disable triggerhappy

検索したり雑誌を読んだりしていると、ofonopsplash-startpsplash-systemdplymouthも止めましょうという話もありますが、今回のインストールではもともと入っていませんでした。

aptの日次更新を止める

 AutoAptEnable0に。エディタで開いて該当部分を書き換えればいいのですが、たった1箇所を探すのが面倒なのでsedでやっちゃいます。

command
sudo sed -i 's/^AutoAptEnable=1/AutoAptEnable=0/' /usr/lib/apt/apt.systemd.daily

ntp問い合わせ先の設定

 上記でsystemd-timesyncdを止めてしまっているので起動スピードには直接関係がないですが、起動後に時刻合わせをしたくなった時、ntpが聞きに行くサーバが遠いとレスポンスも遅くなるので、日本用のを使うようにします。
 こちらを参考に、timesyncdの設定を変更しました。

command
sudo nano /etc/systemd/timesyncd.conf
/etc/systemd/timesyncd.conf
[Time]
NTP=ntp.nict.jp
FallbackNTP=ntp1.jst.mfeed.ad.jp ntp2.jst.mfeed.ad.jp ntp3.jst.mfeed.ad.jp

時刻が合っていないと、SSL通信をする際の証明書照合でエラーになります。aptやpipなどでパッケージのインストールや更新をするときにSSL通信が必要なことがあるので、その前には時刻合わせをしておく必要があるでしょう。

command
cat >~/timeadjust.sh <<EOF
#!/bin/bash
sudo systemctl enable systemd-timesyncd.service
sudo systemctl restart systemd-timesyncd.service
sudo systemctl disable systemd-timesyncd.service
EOF
chmod +x ~/timeadjust.sh

として、ホームディレクトリにtimeadjust.shを作っておけば

command
~/timeadjust.sh

で時刻合わせができます。

SDカードの延命処置

 参考にしたのはこちらです。

 当時はbullseyeだったのでありがたくこの通りやらせていただいていましたが、bookwormで少し事情が変わっています。
 なお、IoTシステムなんかで長期間手許を離れるようなものだとF2FSのようなフラッシュメモリ向けファイルシステムへの変更までしておいたほうがいいのでしょうが、手間がかかるので今回はやっていません。

ログの出力を停止

 ログはbookwormではjournaldに集約されています。

 ログの保存場所はデフォルトで自動的に決定され、あれば/var/log/journal、なければ/run/log/journalです。df -Tで確認すると、/runはファイルシステムがtmpfsですが、これは後述の設定でRAMディスク化してしまうので、/var/log/journalが存在しなければSDカードには書き込まれないことになります。

command
ls -r /var/log/journal

で確認しておきます。

ls: cannot access '/var/log/journal': No such file or directory

と出なかった(つまり存在している)場合は、

command
sudo rm -r /var/log/journal

で削除しておきましょう。

ログの更新頻度とバックアップを抑制

 /var/log/には他のログがあり、それがローテーションでバックアップされていくのがSDカードを傷めていくと言われているので、止めてしまいます。
 logrotateの設定ファイルをsedで書き換えます。頻度をmonthlyに、ローテーションをrotate 0にします。

command
sudo sed -i 's/daily$/monthly/' /etc/logrotate.conf
sudo sed -i 's/weekly$/monthly/' /etc/logrotate.conf
sudo sed -i 's/rotate .*$/rotate 0/' /etc/logrotate.conf

 また、/etc/logrotate.d/には個別のログ更新設定ファイルが保存されているので、全部書き換えます。
 この中にはrotateの指定が2か所あるものもあるので、gをつけて全て対象にします。

command
sudo sed -i 's/daily$/monthly/g' /etc/logrotate.d/*
sudo sed -i 's/weekly$/monthly/g' /etc/logrotate.d/*
sudo sed -i 's/rotate .*$/rotate 0/g' /etc/logrotate.d/*

スワップファイルのRAMディスク化

 まず、スワップファイルを止め、dphysを削除します。

command
sudo swapoff --all
sudo /etc/init.d/dphys-swapfile stop
sudo apt purge -y dphys-swapfile

 Zramの導入は一発でできるようになってます。ありがたいことです。
 aptのアップデートはやっておきましょう。

command
sudo apt update
sudo apt install -y zram-tools

 今回の環境では調整するほどのRAMサイズが元々ないので、デフォルトのままにしました。RAM容量の大きいモデルを利用する場合は調整を考えてください。

tmpフォルダのRAMディスク化

 大変参考になった元ネタはこちら。

command
sudo nano /etc/fstab

次の3行を追記します。

/etc/fstab
tmpfs /tmp     tmpfs defaults,size=32m,noatime,mode=1777 0 0
tmpfs /var/tmp tmpfs defaults,size=16m,noatime,mode=1777 0 0
tmpfs /var/log tmpfs defaults,size=16m,noatime,mode=0755 0 0

 /var/tmpはRAMディスク化するな、というのがArch wikiに書かれているそうです。筆者の環境では問題なく動いていますが、やめた方が無難かもしれません。

これを行ってしまうと、後々導入するライブラリやパッケージが領域不足でビルドできなくなることがありました。RPi3A+を使いましたが、RAMディスクの容量を64MB以上にするとビルド中にハングアップしてしまいます(たぶんメインメモリが足りない)。ビルド中に画面が止まるようなら失敗とみて、このビルドの間だけRAMディスク化を解除したほうが良さそうです。

command
sudo sed -i 's/^tmpfs /#tmpfs /g' /etc/fstab

行の先頭にtmpfsがあれば#をつけてコメントアウト、というコマンド。実行したら再起動して、ビルドし直してください。終わったら逆の

command
sudo sed -i 's/^#tmpfs /tmpfs /g' /etc/fstab

を行って再起動すればOKです。

クリーンアップ

 先述の元ネタではRAM環境で起動を確認してからにされてますが、横着してリブートせずに進めます。真面目な方は元ネタの通りに進めたほうがいいでしょう。

command
sudo apt autoremove
sudo apt autoclean
sudo rm -rf /var/lib/apt/lists/*
sudo rm -rf /var/cache/apt/archives/*
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*
sudo rm -rf /var/log/*
sudo rm /var/swap

 再起動後にもろもろ有効になります。

その他、注意点

  • bookwormではオーディオサブシステムがPulseAudioからPipeWireへ変更された、という話ですが、RPiOS LiteではPipeWireどころかPulseAudioすら入っていませんでした。
  • pythonで利用していたRPi.GPIOが廃止されています。gpiozeroなどに移行する必要があります。
  • pythonの環境は仮想化が推奨されるようになりました。とはいえ、RPiの環境なんて仮想化せずとも、プロジェクトごとに安いSDカードを差し替えれば良い話と思っているので、ライブラリの導入時にはpipの--break-system-packagesオプションで強引にやってしまっています。sudoでやるとインストール後「venvとか使えや」って言われますが、筆者は知らん顔しています。ちゃんとvenvで対応したい方はこちらの素晴らしい記事を参考にしてください。

 なにか気づけば追記していきます。

余談

 このあたりのコマンドは動作確認に役に立ちました。

command
# インストールされているパッケージをすべて表示
sudo apt list --installed
# 現在実行されているサービスの一覧
sudo systemctl | grep running
# システム起動時のパフォーマンス
systemd-analyze time
# systemd各ユニットの初期化時間
systemd-analyze blame
# CPUの温度
vcgencmd measure_temp
# CPUの現在のクロック数
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?