CoderDojo向けにRaspberry Piをセットアップする
CoderDojo西神では、ニンジャが利用できる学習用PCとしてRaspberry Pi 5および4を複数台用意しています。
このRasPiですが、初期インストール時に作成したアカウントに対してsudo権限が付与されています。つまり、初期インストール時のアカウントをニンジャに提供すると、root権限を渡しているのと同じ状況になります。また、RasPiは他のニンジャと共用しますので、他のニンジャの履歴などを参照できてしまいます。これは問題です。
はじめに
ニンジャが安心してRasPiを使えるように、メンターとしても気兼ねなくRasPiを使ってもらうために、プライバシーやセキュリティ等の視点から、共用のRasPiは適切に設定しておく必要があります。
解決すべき課題
セキュリティ確保
ニンジャがsudoで好き勝手できてしまう → ニンジャに管理者権限を与えない
プライバシー保護
他ニンジャと共用するので、作成したファイルやブラウザの閲覧履歴などが後から利用するニンジャによって参照される可能性がある → 共用しても履歴等を参照できないようにする
トラブル防止
配線に足を引っ掛けたりして電源断した場合にストレージ上のデータが破損する可能性がある → 突然の電源断でもデータが壊れないようにする
解決の手段
ニンジャが利用するユーザアカウントからsudo権限を剥奪し、これとは別にsudoを実行できる管理用のアカウントを追加します
オーバーレイ・ファイルシステム (以下、Overlay FS) を有効にすることで、ローカルへの変更はメモリ上に保存し、電源オフ・再起動時に変更を破棄する (ストレージに変更が反映されない) ようにします。これにより、意図しない電源断によるファイルシステムの破壊も防ぎます
デメリット
パッケージが自動的に更新されなくなるので、セキュリティ面でのリスクを抱える可能性があります
システム更新のたびにOverlay FSの無効化/有効化が必要になります。Overlay FSが有効な状態でシステム設定を変更しても、再起動時に破棄されます (永続化されません)
学習の成果をローカルに永続的に保存することができなくなります。ニンジャがUSBメモリ等を用意する必要があります
セットアップ手順
以下の手順でRasPiをセットアップします。NVMe SSDを組み込んだRasPi5で確認しています。
OSインストール
Imagerのインストール先デバイス選択の次の設定画面で、デフォルトのログインユーザ名とパスワードを設定します。
ここではユーザ名をninjaとしています。ニンジャはこのアカウントでRasPiにログインして学習することになります。
基本的なセットアップ
OSイメージを焼いてRasPiを起動したら、基本的なセットアップを行います。RasPi5で日本語を使うための基本的な設定については、下記の記事にまとめています。基本的にはRasPi4でも同じです。
アプリのインストール
標準インストール状態で、Python3インタプリタやGCCコンパイラ、これらを利用するThonnyやGeanyといったIDEがインストールされています。これらに加えて、必要であればVSCodeやJetBrains IDEなどをインストールします。
例えば、VSCodeをインストールするには以下のようにaptを実行します。必要に応じてインストール後にVSCodeを起動し、日本語化パックなどを導入しておきましょう。
sudo apt update
sudo apt -y install code
パッケージの更新・クリーンアップ
Overlay FSを有効にしてローカルへの反映ができなくなる前に、パッケージを最新のものに更新しておきましょう。
$ sudo apt update
$ sudo apt -y upgrade
更新が完了したら、ダウンロードしたパッケージファイルは削除しておきましょう。
$ sudo apt clean
管理用アカウントを追加
ニンジャ用のアカウントとは別に、管理用のアカウントを作成します。ここでは仮にadminとします。
$ sudo adduser admin
ユーザ `admin' を追加しています...
新しいグループ `admin' (1001) を追加しています...
Adding new user `admin' (1001) with group `admin (1001)' ...
ホームディレクトリ `/home/admin' を作成しています...
`/etc/skel' からファイルをコピーしています...
新しい パスワード:
新しい パスワードを再入力してください:
passwd: パスワードは正しく更新されました
admin のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
フルネーム []: Administrator
部屋番号 []:
職場電話番号 []:
自宅電話番号 []:
その他 []:
以上で正しいですか? [Y/n] y
Adding new user `admin' to supplemental / extra groups `users' ...
ユーザ `admin' をグループ `users' に追加しています...
管理アカウントが作成できたら、このアカウントに諸々の権限を付与するためにグループに属させます。基本的にデフォルトユーザと同じ権限を付与しておけば大丈夫です。まずはninjaユーザが属しているグループを確認します。
$ groups ninja
ninja : ninja adm dialout cdrom sudo audio video plugdev games users input render netdev spi i2c gpio lpadmin
adm以降のグループに追加しましょう。sudo vigrしてもよいですが、ここはusemodコマンドで済ませます。グループのリストはカンマ区切りで指定します。usermodが正常終了したら、groupsコマンドで正しく設定されているか確認します。
$ sudo usermod -aG adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,render,netdev,spi,i2c,gpio,lpadmin admin
$ groups admin
admin : admin adm dialout cdrom sudo audio video plugdev games users input render netdev spi i2c gpio lpadmin
sudo権限の設定
追加した管理ユーザがsudoを使えるようにします。が、実はこの時点で管理ユーザはsudoグループに属していますので、追加で設定は必要ありません。ただし、sudo実行時にパスワードを求められます。セキュリティと利便性のトレードオフですが、ここではsudo実行時にパスワードが要求されるままにしておきます。
次に、/etc/sudoers.d/010-pi_nopasswd に記述されているninjaの行の先頭に # を挿入し、コメントアウトします。vi等で直接編集せず、visudoコマンドを使って安全にファイルを編集しましょう。
$ sudo visudo -f /etc/sudoers.d/010_pi-nopasswd
# ninja ALL=(ALL) NOPASSWD: ALL
最後に、gpasswdコマンドでninjaユーザをsudoグループから削除し、sudoコマンドを実行できないようにします。usermodコマンドと引数の順番が逆 (アカウントが先) なので注意が必要です。
$ sudo gpasswd -d ninja sudo
[sudo] ninja のパスワード:
ユーザ ninja をグループ sudo から削除
$ groups ninja
ninja : ninja adm dialout cdrom audio video plugdev games users input render netdev spi i2c gpio lpadmin
上記の設定でnopasswdを無効にしたので、ここでのsudoコマンドの実行時にはパスワードを求められます。gpasswdが成功したら、groupsコマンドでsudoグループに入っていないことを確認します。
なお、この時点ではログイン時点でのグループ情報を保持しているので、ログアウト/再起動するまでninjaアカウントでもsudoを使えます。
自動更新の停止
この次に設定するOverlay FSを有効にすると、ファイルシステムへの変更がストレージに保存されなくなります。そのため、定期的なパッケージ更新が無意味になります。Overlay FSの領域を圧迫することにもなりますので、これらの自動更新系のサービスは停止しましょう。
$ sudo systemctl stop apt-daily.timer
$ sudo systemctl stop apt-daily.service
$ sudo systemctl disable apt-daily.timer
$ sudo systemctl disable apt-daily.service
$ sudo systemctl stop apt-daily-upgrade.timer
$ sudo systemctl stop apt-daily-upgrade-service
$ sudo systemctl disable apt-daily-upgrade.timer
$ sudo systemctl disable apt-daily-upgrade.service
依存関係により、timer → serviceの順にstopする必要があります。
なお、下記のパッケージ更新の項でも触れますが、パッケージが自動更新されなくなりますので、セキュリティ的に脆弱になるリスクがあります。定期的にOverlay FSを無効にしてパッケージを更新することが必要です。
Overlay FSの有効化
Overlay FS (オーバーレイ・ファイルシステム) を有効にすると、ファイルシステムへの変更はメモリ上に保存され、ストレージには反映されなくなります。つまり、仮に破壊的な操作を行ってしまったとしても、再起動してしまえばアラ不思議、なかったことになります。
$ sudo raspi-config
なお、ここからのスクショはWindowsにインストールしたUbuntu 22.04 LTS (WSL2) からsshでリモートログインして操作したものです。
raspi-configを起動したら、Performance OptionsからOverlay File Systemを選択します。
Overlay FSを有効にするか訊かれるので「はい」を選択すると、有効にしましたと表示されます。ここでいくつかのパッケージが追加でインストールされる場合もあります。
次に、bootパーティションを書き込み保護するか訊かれるので、これも「はい」と答えて書き込みを禁止します。
ここまで設定が済んだら再起動します。
これでOverlay FSの設定は完了です。再起動後はこれまで通り、自動でデフォルトユーザ (ここではninja) でログインされます。試しに適当なファイルを作成して再起動すると、作成したはずのファイルが消えていることが確認できると思います。
この記事の末尾では、よりハードな確認を行っていますので、興味があれば合わせてご確認下さい。
Tips
デスクトップ表示
Overlay FS有効にした後、デスクトップに見慣れないドライブがマウントされています。どうやらドライブの実体とオーバレイしたドライブが/media以下にマウントされるらしく、これをRasPiのデスクトップ環境が画面にアイコンとして表示してしまうようです。
デスクトップを右クリックして「デスクトップの設定」を開き、「マウントされたディスク」のチェックを外せば、これらのアイコンは表示されなくなります。
これでデスクトップ上に余計なドライブは表示されなくなります。ただし、USBメモリやDVDドライブにメディアを挿入した時にもドライブが表示されなくなりますので、注意が必要です。
……Overlay FSを有効にしていますので、再起動するとこの設定は元に戻ります。この設定を永続化するには、raspi-configでOverlay FSを無効にして再起動してからこのデスクトップ設定を行う必要があります。
なお、ちょっと調べた限りでは、デスクトップに表示するマウントされたストレージを /media/{username} 以下に制限する方法はないようです。
CoderDojo開催時の運用
あるニンジャがRasPiを利用した後は、必ず一度は再起動 (または電源オフ) してから次のニンジャに利用してもらいます。
パッケージ更新
定期的なパッケージの自動更新を無効にしていますので、Overlay FSを無効にしてから手動でパッケージを更新する必要があります。デフォルトユーザはsudoを使えなくしましたので、管理ユーザで実行する必要があります。
$ sudo apt update
$ sudo apt -y upgrade
...
$ sudo apt clean
更新が終わったらクリーンアップし、Overlay FSを有効に戻すのをお忘れなく。
定期処理の無効化
定期的なパッケージの自動更新を無効化しましたが、他にも定期的に実行される処理があります。一覧にして確認してみましょう。
$ sudo systemctl list-timers --all
NEXT LEFT LAST PASSED UNIT ACTIVAT>
Wed 2024-03-06 22:38:52 JST 22h left Tue 2024-03-05 22:38:52 JST 1h 31min ago systemd-tmpfiles-clean.timer systemd>
Thu 2024-03-07 00:00:00 JST 23h left Wed 2024-03-06 00:00:17 JST 10min ago dpkg-db-backup.timer dpkg-db>
Thu 2024-03-07 00:00:00 JST 23h left Wed 2024-03-06 00:00:17 JST 10min ago logrotate.timer logrota>
Thu 2024-03-07 06:29:18 JST 1 day 6h left Wed 2024-03-06 00:04:26 JST 6min ago man-db.timer man-db.>
Sun 2024-03-10 03:10:42 JST 4 days left Tue 2024-03-05 22:23:18 JST 1h 47min ago e2scrub_all.timer e2scrub>
Mon 2024-03-11 00:01:14 JST 4 days left Tue 2024-03-05 23:08:52 JST 1h 1min ago fstrim.timer fstrim.>
6 timers listed.
見た感じ、dpkg-db-backupとman-dbは止めてもよさそうです。サービス停止は自己責任でお願いします。
$ sudo systemctl stop dpkg-db-backup.timer
$ sudo systemctl stop dpkg-db-backup.service
$ sudo systemctl stop man-db.timer
$ sudo systemctl stop man-db.service
キーボードレイアウト設定
現時点でのRasPi OSでは、Wayfireコンポジタの設定管理ツールであるwcm (Wayfire Config Manager) がRasPiパッケージとして提供されていません。デスクトップの設定でキーボード配列を変更しようとすると、システム全体の設定が変更されます (sudo権限を求められます) 。
デフォルトのユーザは標準の日本語配列キーボードを使い、管理ユーザは英語配列キーボードに差し替えて利用する、というケースでは、管理ユーザの設定ファイルを直接編集する必要があります。
例えば、管理ユーザはHHKBに差し替えて利用したい場合は、管理ユーザでログインし、以下のような設定を行います。既存のエントリがあれば書き換えましょう。
$ vi ~/.config/wayfire.ini
…
[input]
xkb_layout = us
xkb_model = hhk
xkb_options =
xkb_variant =
...
一度ログアウトしてログインし直すと反映されると思います。もちろん、設定を永続的に保存するにはOverlay FSを無効にしておく必要があります。
Overlay FSの検証
Overlay FSを有効にしたら、破壊的な操作も再起動すればなかったことになるのか確認してみます。Overlay FSを有効にしたRasPi4にsshでリモートログインし、お約束とも言える以下のコマンドを実行してみました。
$ sudo rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe
はい、このコマンドは今時のLinuxではエラーになります。エラーメッセージに従ってオプションを付けて再度実行してみましょう。
$ sudo rm -rf --no-preserve-root /
rm: cannot remove '/run/rpc_pipefs/gssd/clntXX/gssd': Operation not permitted
...
(膨大な量のメッセージ)
...
rm: cannot remove '/media/root-ro/var/mail': Read-only file system
エラーメッセージが表示される通り、一部のファイル・ディレクトリは削除できませんでしたが、それら以外は削除できたようです。本当にファイルが消えたか確認してみましょう。
$ pwd
/home/ninja
$ ls
-bash: ls: command not found
$ cd /
$ pwd
/
$ ls
-bash: ls: command not found
pwdやcdのようなシェル組み込みのコマンドは実行できましたが、lsはcoreutilsパッケージで提供されるコマンドなので、コマンドの実体であるバイナリファイルが削除されると実行できなくなります。
何もできないので再起動しましょう。
$ sudo reboot
-bash: /usr/bin/sudo: No such file or directory
ですよねー。sudoコマンドも削除されたので再起動できません。RasPi5と違い、RasPi4には電源ボタンがないので、ちょっと怖いですが電源アダプタを引っこ抜いて強制的に電源を落とします。大丈夫かな。
電源を入れ直して……起動しました。何ごともなかったかのように再起動できました。素晴らしい。
ということで、Overlay FSを有効にしておけば、rm -rf / を実行しても大丈夫であることが確認できました。
更新履歴
2024/03/19: タイポ等を修正しました。