【RaspberryPi】イメージの段階でオートログインと初回起動時ユーザー登録を無効化する

# ■ 背景
最近、[yomon8/raspberry-pi-imager ｜GitHub](https://github.com/yomon8/raspberry-pi-imager) を参考にPacker + Docker + Ansible でラズパイイメージの自動生成を実装しています。

しかし困ったことに、最新のイメージは初回起動時にインタラクティブにユーザー登録やキーボード設定を行わないといけません。加えてデフォルトでオートログインが有効になっていたりと、サーバーとして起動することが考慮されていません。

起動後にこれらを設定するのは簡単ですが、イメージを自動生成する都合上、イメージの段階でこれらを設定をしなければなりません。

しかし、方法がどこにも載っておらず、、、かなり苦労したので、調べたことを残しておこうと思います。


# ■ 前準備

特に必要ないのですが、実際にファイルを見ながら理解したい方は↓でラズパイイメージをマウントするといいと思います。

https://qiita.com/ktamido/items/5aed2c53e06d5bcf653f


# ■ デフォルトユーザーの設定
初回起動時にインタラクティブにユーザーを設定させないようにする設定です。
`/boot/userconf` に `ユーザー名:ハッシュ化パスワード` が設定されていると、初回起動時に自動でユーザー作成が行われます。

```bash
touch /boot/userconf

USER="xxxxxxxxx"
PASSWD="yyyyyyyy"
# パスワードをsha256でハッシュ化
HASHED_PASSWD="$(echo $PASSWD | openssl passwd -6 -stdin)"

# "ユーザー:ハッシュ化パスワード" を /boot/userconfに書き込みます
# [注意！] 末尾に改行を含んではいけません！
echo -n "${USER}:${HASHED_PASSWD} > /boot/userconf
```

# ■ オートログインの無効化
起動後だと `/etc/systemd/system/getty@tty1.service.d/autologin.conf` を削除するだけで無効化できるのですが、イメージ段階で無効化する方法がなかなか見つからず、、、結局 `autologin.conf` を生成している `raspi-config` コマンドを書き換えました。

```bash
vim /usr/bin/raspi-config
```

`do_boot_behaviour()` 関数 (1377行目あたり)を書き換えます。
この関数は `/usr/bin/cancel-rename` で `raspi-config nonint do_boot_behaviour B2` のように呼び出され、強制的にオートログインが有効になる仕様です。
なので、B2の分岐で `autologin.conf` が生成されないように修正します。



```bash:/user/bin/raspi-config
do_boot_behaviour() {
  if [ "$INTERACTIVE" = True ]; then
    BOOTOPT=$(whiptail --title "Raspberry Pi Software Configuration Tool (raspi-config)" --menu "Boot Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \
      "B1 Console" "Text console, requiring user to login" \
      "B2 Console Autologin" "Text console, automatically logged in as '$USER' user" \
      "B3 Desktop" "Desktop GUI, requiring user to login" \
      "B4 Desktop Autologin" "Desktop GUI, automatically logged in as '$USER' user" \
      3>&1 1>&2 2>&3)
  else
    BOOTOPT=$1
    true
  fi
  if [ $? -eq 0 ]; then
    case "$BOOTOPT" in
      B1*)
        systemctl --quiet set-default multi-user.target
        rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
        ;;
      B2*)
        # *** *** *** 修正 (ここから) *** *** ***
        # autologin.confが生成されないように修正
        systemctl --quiet set-default multi-user.target
        rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
#        systemctl --quiet set-default multi-user.target
#        cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF
#[Service]
#ExecStart=
#ExecStart=-/sbin/agetty --autologin $USER --noclear %I \$TERM
#EOF
        # *** *** *** 修正 (ここまで) *** *** ***
        ;;
      B3*)
        # 略...
        ;;
      B4*)
        # 略...
        ;;
    esac
    systemctl daemon-reload
    ASK_TO_REBOOT=1
  fi
}
```



一応参考までに、 `cancel-rename` は **userconf-pi** パッケージに含まれるリソースで、初回起動時にユーザーをリネームする機能のようです 。 ([RPi-Distro/userconf-pi | GitHub](https://github.com/RPi-Distro/userconf-pi))
※ `cat /var/lib/dpkg/info/userconf-pi.list` に **cancel-rename** があります。
※ [New package userconf-pi? | RaspberryPi](https://forums.raspberrypi.com/viewtopic.php?t=332669)
<font color="red">※ ちなみに、 **userconf-pi** をアンインストールしてしまうと、ログインプロンプトが表示されなくなって、ログインできなくなります。</font>

```bash:/usr/bin/cancel-rename
#!/bin/bash

if [ "$(id -u)" != "0" ]; then
    echo "Please run with 'sudo': sudo cancel-rename USER" >&2
    exit 1
fi

if [ "$(raspi-config nonint get_boot_cli)" -ne 0 ]; then
    if [ "$1" = "root" ] || ! getent passwd "$1" >/dev/null; then
        echo "Please specify default user: sudo cancel-rename USER" >&2
        exit 1
    fi
    # set up autologin
    SUDO_USER="$1" raspi-config nonint do_boot_behaviour B4

    # remove the autostart for the wizard
    rm -f /etc/xdg/autostart/piwiz.desktop

    # set up a self-deleting autostart to delete the wizard user
    cat <<- EOF > /etc/xdg/autostart/deluser.desktop
        [Desktop Entry]
        Type=Application
        Name=Delete Wizard User
        NoDisplay=true
        Exec=sh -c 'sudo userdel -r rpi-first-boot-wizard; sudo rm /etc/sudoers.d/010_wiz-nopasswd; sudo rm /etc/xdg/autostart/deluser.desktop'
        EOF
else
    SUDO_USER="$1" raspi-config nonint do_boot_behaviour B2
fi

systemctl --quiet disable userconfig
systemctl --quiet enable getty@tty1 --now --no-block
```



# ■ sshd有効化
デフォルトでsshdは無効です。
ラズパイでは初回起動時に `/boot/ssh` というファイルが存在するとsshdが有効になります。

```bash
# sshd有効化
touch /boot/ssh
```


# ■ キーボード設定
jis配列のキーボードを使うための設定を行います。

```bash
touch /etc/default/keyboard
```

```txt:/etc/default/keyboard
# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="jp"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"
```

# ■ WiFiの有効化
ラズパイのwifiは地域情報を設定しないと有効化できません。 
※ 電波法とかの関連で無線規制区域を設定ファイルに書かないといけないらしいです。
`wpa_supplicant.conf` に `country=JP` を追記します。

```bash
touch /etc/wpa_supplicant/wpa_supplicant.conf
```

```conf:/etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP
```

# ■ timezone設定
timezoneを `Asia/Tokyo` に設定します。
```bash
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```


# ■ 参考
- [Raspberry Pi実機無しでゴールデンイメージを作成する(SORACOM接続用サンプル） |  YOMON8.NET](https://yomon.hatenablog.com/entry/2021/08/generate_raspberrypi_image_with_packer)
- [yomon8/raspberry-pi-imager | GitHub](https://github.com/yomon8/raspberry-pi-imager)