RaspberryPi OS Lite を CUI でインストールしてヘッドレスでログイン


RaspberryPi OS はかつては 初期ユーザー・パスワードが pi/raspberry でした。その後パスワードは初期ログイン時に変更が必要となり、 2022年頃からは初期ユーザも指定が必要となりました。

一般的にはディスプレイ・キーボードを接続して設定するか、公式ツールである Raspberry Pi Imager で SD カードにイメージを書き込む時に同時に設定します。

しかしながらヘッドレスでの操作に慣れているといちいちディスプレイやキーボードを接続するのはめんどくさく、GUIツールもかったるく感じてしまいます。

ここではヘッドレスで RaspberryPi を起動する前提で、Raspberry Pi Imager を使わずに ssh でログインできるユーザー・パスワードの設定をする方法を探ります。

# 環境

- 母艦PC
  -  Ubuntu 2.04
- RaspberryPi B+
  - RaspberryPi OS Lite 
  - 2024-07-04-raspios-bookworm-armhf-lite.img.xz

# 方法

`/boot/cmdline.txt` に `init` パラメータを追記したり、`/usr/lib/raspi-config/init_resize.sh` スクリプトをフックしたりすることも考えたがプリミティブに `/etc/shadow` を編集する方法を採りました。


# 調査

microSD カードにイメージを展開した直後の `/etc/passwd`
```
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
pi:x:1000:1000:,,,:/home/pi:/bin/bash
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:100:107::/nonexistent:/usr/sbin/nologin
_rpc:x:101:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:102:65534::/var/lib/nfs:/usr/sbin/nologin
sshd:x:103:65534::/run/sshd:/usr/sbin/nologin
avahi:x:104:110:Avahi mDNS daemon,,,:/run/avahi-daemon:/usr/sbin/nologin
polkitd:x:996:996:polkit:/nonexistent:/usr/sbin/nologin
dnsmasq:x:105:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
```



ふむ、pi ユーザはすでに定義されているのですね。

一方  `/etc/shadow` は・・・

```
root:*:19908:0:99999:7:::
daemon:*:19908:0:99999:7:::
bin:*:19908:0:99999:7:::
sys:*:19908:0:99999:7:::
sync:*:19908:0:99999:7:::
games:*:19908:0:99999:7:::
man:*:19908:0:99999:7:::
lp:*:19908:0:99999:7:::
mail:*:19908:0:99999:7:::
news:*:19908:0:99999:7:::
uucp:*:19908:0:99999:7:::
proxy:*:19908:0:99999:7:::
www-data:*:19908:0:99999:7:::
backup:*:19908:0:99999:7:::
list:*:19908:0:99999:7:::
irc:*:19908:0:99999:7:::
_apt:*:19908:0:99999:7:::
nobody:*:19908:0:99999:7:::
systemd-network:!*:19908::::::
pi:!:19908:0:99999:7:::
systemd-timesync:!*:19908::::::
messagebus:!:19908::::::
_rpc:!:19908::::::
statd:!:19908::::::
sshd:!:19908::::::
avahi:!:19908::::::
polkitd:!*:19908::::::
dnsmasq:!:19908::::::
```
pi ユーザのパスワードは無効になっているのがわかります。

また、適切に設定されたユーザのパスワードは yescrypt という形式でした。
```
nanbuwks:$y$j9T$FK4j//L3j15Zqk9fQC7TB1$Dbrbs3pON97krn0.aQmY9N.o8AhuTzYbIocrVCuldE5:20012:0:99999:7:::
```
cf.,「yepasswd で パスワードを生成」
https://qiita.com/nanbuwks/items/5715007b63c454c22c7e

# 作業

上記の調査結果を元に、 /etc/shadow の ! をパスワードハッシュに入れ替える作業を行います。

cf., 「chpasswd コマンドを使ってパスワードを非対話的に変更する」
https://qiita.com/nanbuwks/items/5715007b63c454c22c7e

まずは母艦PCに mkpasswd コマンドをインストールし、
```
$ sudo apt install whois
```
以下のようにしてyescrypt形式のハッシュを得ます。

```
$ echo hogehoge | mkpasswd --stdin
$y$j9T$ozt7RXgFdCmzAqgnCMNMj.$/ltOUs9uyZSvDavPV6BoZRmD7IBeRksHLGrsUvnxZ00
```
:::note
hogehoge はまともなパスワードに入れ替えて作業してください。
:::

出てきたハッシュ値を shadow ファイルに当てはめて以下のようにします。
```
pi:$y$j9T$.hgjjPTDxLLeVkKqxFOif0$Sv.FhP6nzYuINLgYId6fi3VYpemBVvVIY6ICdq8Z/D9:19908:0:99999:7:::
```

`shadow` ファイルは、 今回 microSD を刺した母艦では  `/media/nanbuwks/rootfs/etc/shadow` となってました。

また、ssh で作業するために `/media/nabnuwks/bootfs/` 上に `ssh` ファイルを適当に作っておきます。

# 起動

Raspberry Pi に microSD を装着し、起動します。今回は有線LANで接続したため、しばらく待つと母艦側から以下のように反応があります。


```
$ ping raspberrypi.local
PING raspberrypi.local (192.168.0.102) 56(84) bytes of data.
64 bytes from 192.168.0.102 (192.168.0.102): icmp_seq=1 ttl=64 time=1.37 ms
^C
```

ssh でアクセスします。

```
$ ssh pi@raspberrypi.local
300a24

The authenticity of host 'raspberrypi.local (192.168.0.102)' can't be established.
ED25519 key fingerprint is SHA256:7NxF52dMEExiTkE1TId78YxvsiQdGhLFfvhutfy59vM.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'raspberrypi.local' (ED25519) to the list of known hosts.
Please note that SSH may not work until a valid user has been set up.

See http://rptl.io/newuser for details.
pi@raspberrypi.local's password: 
Linux raspberrypi 6.6.31+rpt-rpi-v6 #1 Raspbian 1:6.6.31-1+rpt1 (2024-05-29) armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
pi@raspberrypi:~ $ 
```
ログオンできました。