2021/12/20
KAICHO: s_naray[at]yahoo[dot]co[dot]jp
※SPAM防止のため捻ってある

TinyPilot設定

■はじめに

本文書は、RaspBerryPi 4BでTinyPilotを設定する場合の、 個人的なカスタム方法について述べる。 間違ってたら教えてね。

■TinyPilotとは

PCをリモートから操作するためのRaspberryPi 4Bシステム。具体的には、 リモートKVM(Keyboard/Video/Mouse)を実現する。所謂HPEのiLOMやDellの iDRACのリモートコンソールの真似事ができる。でもリモートでPCを 強制リセットしたり電源On/Offしたりはできないのでご注意。 詳細は以下のURL群を参照。

■インストール方法とか

…は、上の文書見ればわかるだろうから省略。気が向けば書くかも。

最終的には、RaspberryPi 4BにUSB-HDMIキャプチャデバイスを追加し、以下のように接続することで、TinyPilotシステムとして動作するようになる。

■デフォルト設定からの変更

TinyPilotの初期設定が終わり、一通り動作確認をしたら、 実運用に備えて細かい設定変更を施す。我輩は設定変更で以下を実現した。

順番に見ていこう。

piユーザとrootのパスワード変更

デフォルトでは、TinyPilotは(というかRaspberryPiは) pi ユーザがパスワード raspberry でログインできるようになっている。 まずはこれを変更しよう。

$ passwd
Changing password for pi.
Current password:
New password:
Retype new password:
passwd: password updated successfully
$

また、rootのパスワードも変更しよう。sudo su - でrootになってもよい。

$ sudo passwd root
(略)

rootユーザでsshログインできるようにはなっていないので、 そうしたいなら /etc/ssh/sshd_config に "PermitRootLogin yes" を追記 または既存の記述を変更して、systemctl restart sshd で設定を反映する。

Webページのパスワード保護

デフォルトでは、TinyPilotのWebページ(http://IPアドレス/) はパスワード保護されていない。これだと誰か知らない人にアクセスされて 好き放題されちゃう可能性があって極めて危険なので、とにもかくにも パスワード保護することにする。

TinyPilotのWebサーバは nginx が採用されているため、設定ファイルは /etc/nginx 以下に存在する。どうせその用途にしか使わないんだから、 .htpasswordファイルは /etc/nginx/.htpassword として作ってしまった方が 管理が楽だ。以下の例では、tpuser というユーザを作成している。

$ sudo htpasswd /etc/nginx/.htpasswd tpuser
New password:
Re-type new password:
Adding password for user tpuser
$

それが終わったら、nginx の設定ファイル /etc/nginx/sites-enabled/tinypilot.conf の server セクション中に、以下を追記する。

    location / {
      proxy_pass http://tinypilot;
      auth_basic "Restricted";
      auth_basic_user_file /etc/nginx/.htpasswd;
    }

systemctl restart nginx で nginx を再起動して設定を反映すれば、 パスワード保護は完了だ。http://IPアドレス/ にアクセスしてパスワードを 聞かれることを確認すればよい。

WebページのSSL化(https://でアクセスできるように)

https://でアクセスできるようにするには、まず自己署名でいいので証明書を 作成する必要がある。以下では /etc/nginx/cert/ 以下に cert.key と cert.csr を作成した。

# mkdir /etc/nginx/cert
# cd /etc/nginx/cert
# openssl genrsa -aes192 -out cert.key 4096
(略)
Enter pass phrase for cert.ke:
Verifying - Enter pass phrase for cert.key:
#
# openssl req -new -key cert.key -out cert.csr
Enter pass phrase for cert.key:
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:root@localhost
(snip)
#

その後、nginx の設定ファイルを、http(port80)からhttps(port443)を 待ち受けするように変更する。

    listen  80 default_server;
    listen  [::]:80 default_server;

の部分を、以下のように書き換える。

    listen   443 ssl default_server;
    listen   [::]:443 ssl default_server;
    ssl on;
    ssl_certificate "/etc/nginx/cert/cert.crt";
    ssl_certificate_key "/etc/nginx/cert/cert.key";

systemctl restart nginx で nginx を再起動して設定を反映すれば、 http:// の代わりに https:// でアクセスできるようになっているはず。

おまけとして、http:// でアクセスされた時に https:// に転送する 設定を /etc/nginx/sites-enabled/tinypilot.conf や /etc/nginx/conf.d/ 以下に追加するといいかもしれない。

server {
    listen 80;
    server_name tinypilot;
    return 301 https://$host$request_uri;
}

不要なデバイスの停止

TinyPilotでは、(ちょっと工夫しない限り、)USBケーブルで監視対象PCから 電源を得る。USB2.0だと電源的にはかなり頼りないので、なるべく消費電力が 少なくなるよう、使わないデバイスを停止することを考える。 また、ファンレス運用が普通だろうから、温度が高くなった時の対策も必要だ。

今回は以下の対策を施す。

とはいえ、設定は簡単で、/boot/config.txt 末尾に以下を追記するだけ。この設定の /boot/overlays/README に書いてあるので必要に応じて参照。

/boot/config.txt への追記内容
# disable bluetooth and wifi
dtoverlay=disable-bt
dtoverlay=disable-wifi

# lower CPU clock when high temp(65C')
temp_limit=65

あとおまけ。音なんか要らんという人は、audio=on になっている部分を off に変更。これで更に省電力化…かも?

/boot/config.txt の変更内容
# Enable audio (loads snd_bcm2835)
#dtparam=audio=on   ← これがデフォルト
# Disable audio
dtparam=audio=off   ← このように変更

電力抑制のためのスクリプト用意

TinyPilot上で top コマンドを実行すると、ustream周りのプロセスやビデオキャプチャデバイスのkernel daemonがCPUを利用していることに気づく。下の例では pid 66 とか 552 とか。 これはRaspberryPiの消費電力と温度の上昇に関わってくる。

何もしていないときのTinyPilotのtop出力
top - 13:40:59 up 3 min,  1 user,  load average: 0.22, 0.32, 0.15
Tasks: 133 total,   1 running, 132 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  :  1.3 us,  1.6 sy,  0.0 ni, 97.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3838.7 total,   3623.5 free,     84.3 used,    131.0 buff/cache
MiB Swap:    100.0 total,    100.0 free,      0.0 used.   3615.5 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  66 root       0 -20       0      0      0 I   3.0   0.0   0:04.87 kworker/u9:0-uvcvideo
 552 ustream+  20   0   51696    704    588 S   1.7   0.0   0:02.31 main 
  823 pi        20   0   10324   2908   2476 R   0.7   0.1   0:00.22 top
  809 pi        20   0   12204   3624   2836 S   0.3   0.1   0:00.03 sshd
    1 root      20   0   15272   7832   6288 S   0.0   0.2   0:04.20 systemd
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 kthreadd
    3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp

リモートKVMとしてTinyPilotを使う場合、ustreamerもnginxも、USB-HDMIキャプチャも常に動いている必要はない。アクセスが必要になった時だけ 手作業で開始させればいい。 だったら、これらを停止・開始するスクリプトを作っておくと便利JAN?

というわけで、以下のようなスクリプトを書いた。TinyPilot-stop.sh が 常時起動不要なサービスを停止するスクリプト、TinyPilot-start.sh が 必要になったときにこれらを起動するスクリプト。USBVIDEODEVは 皆様の環境でUSB-HDMIキャプチャデバイスが刺さっているデバイスを、 lsusb -t か何かで確認して適宜変更すること。

TinyPilot-stop.sh
#!/bin/sh


# Bus 1, Port 1, Port 3
USBVIDEODEV="1-1.3"
SERVICES="nginx ustreamer"


error_end() {
    echo $*
    exit 1
}



for i in $SERVICES; do
    echo -n "stopping service $i ... "
    systemctl status $i > /dev/null
    ret=$?
    [ "$ret" = 3 ] && echo "stopped, skip" && continue
    [ "$ret" != 0 ] && error_end "status($ret) is not 0 or 3"
    systemctl stop $i > /dev/null
    [ "$?" != 0  ] && error_end "failed"
    echo "OK"
done



# disconnect USBVIDEO
echo "Disconecting USBVIDEO(on $USBVIDEODEV)"
echo -n "$USBVIDEODEV" > /sys/bus/usb/drivers/usb/unbind
#[ "$?" != 0 ] && error_end "failed(ret=$?)"
# echo "OK"


echo "done."

TinyPilot-start.sh
#!/bin/sh


# Bus 1, Port 1, Port 3
USBVIDEODEV="1-1.3"
SERVICES="ustreamer nginx"


error_end() {
    echo $*
    exit 1
}


# connect USBVIDEO
echo "Conecting USBVIDEO(on $USBVIDEODEV)"
echo -n "$USBVIDEODEV" > /sys/bus/usb/drivers/usb/bind
#[ "$?" != 0 ] && error_end "failed(ret=$?)"
# echo "OK"


for i in $SERVICES; do
    echo -n "starting service $i ... "
    systemctl status $i > /dev/null
    ret=$?
    [ "$ret" = 0 ] && echo "started, skip" && continue
    [ "$ret" != 3 ] && error_end "status($ret) is not 0 or 3"
    systemctl start $i > /dev/null
    [ "$?" != 0  ] && error_end "failed"
    echo "OK"
done

echo "done."

なんとびっくりこれで不要なサービスだのを停止するだけで、RaspberryPiの 温度が5℃くらい下がる。結構効果は大きい。

起動直後からサービス開始する必要がないなら、systemctl で nginx と ustreamer を停止しておくとよい。これで不慮の問題でRaspberry Piが再起動しても、CPU負荷を軽減できる。

nginx と ustreamer を起動時には停止しておく
# systemctl disable nginx
# systemctl disable ustreamer

温度は、以下のようなスクリプトで5分おきにどうなっているか出力させて みるとよい。csv形式になるようにしてみた。

五分おきにRaspberry Piの温度をcsv形式で出力するスクリプト
#!/bin/sh

INTERVAL=300

echo "Date-Time,           Temperature"
while : ; do
    temp=`cat /sys/devices/virtual/thermal/thermal_zone0/temp`
    echo -n `date +"%Y-%m-%d %H:%M:%S"`,
    printf " %d.%03d\n" $((temp/1000)) $((temp%1000))
    sleep $INTERVAL
done

システムアップデート

LinuxやRaspberryPiは結構頻繁にアップデートされている。 最新に追いつきたいなら、 定期的に以下のようなスクリプトを動作させるとよい。ただ、rpi-updateや rpi-eeprom-update は定期的に行うことが推奨されていないそうなので、 マニーな人以外はコメントアウトした方がいいかも。

システムアップデートスクリプト
#!/bin/sh

run() {
  echo executing "$*"
  $*
  echo "exitcode = $?"
  echo ""
}
run apt-get update
run apt-get upgrade
run rpi-update
run rpi-eeprom-update

■その他

ケースにフィンがついている場合、フィンを通って空気が上に抜けるような 形で設置すると冷える。手元の環境では置き方だけで4℃くらい違った。

■おわりに

TinyPilot、便利だ。お安く手軽にリモートKVMを実現する手段としては、 十分アリだと思う。電源On/Offや強制リセットができないのは残念だが、 デスクトップPCなら仕方ないとも思う。