ラズパイのOSを「cloud-init」で簡単に設定（Ubuntu Server 20.04 LTS 64bit）

## 本記事の内容
- ラズパイ用のUbuntuを書き込んだSDカードに対して、PC上で事前に基本設定を行う。
- 本記事で設定したSDカードは、ラズパイに差し込んですぐに使える。  
（ディスプレイやキーボードをつながなくても、SSHで他のPCから操作可能な状態）
- ラズパイ上での各種設定やパッケージ更新などは、「cloud-init」が自動で行ってくれる。

## 前提条件
- ラズパイ3または4（本記事はRaspberry Pi 4 Model B 4GBで動作確認）
- Ubuntu Serverをインストール済みのSDカード（本記事はUbuntu Server 20.04.2 LTS 64bitを使用）
- 設定ファイル編集用のテキストエディタ（私はVS Codeを使用。YAML形式に対応するものが望ましい）
- SSHの基礎知識、接続用クライアント、公開鍵
- ラズパイのネットワーク接続は有線LANを使用

SDカードへのOSインストールは「Raspberry Pi Imager」で簡単に行える。
[ラズパイのOSを「Raspberry Pi Imager」で簡単インストール](https://qiita.com/s8ta/items/57514d618e2607206a4c)

## 作業手順
### 1. SDカードをPCに接続
Ubuntuのイメージを書き込んだSDカードPCに接続する。
ドライブが2つ表示されるが、「system-boot」に以降の手順で編集する設定ファイルが存在する。

### 2. ネットワーク設定
設定ファイル「network-config」を編集し、有線LANのIPアドレスを固定する。

以下は、ルーターのIPアドレスが`192.168.1.1`で、ラズパイのIPアドレスを`192.168.1.10`に固定する場合の例のため、利用環境に合わせて設定する。

#### 有線LANの設定（ethernets）

```yaml:network-config
ethernets:
  eth0:
    addresses:
      - 192.168.1.10/24
    gateway4: 192.168.1.1
    nameservers:
      addresses: [192.168.1.1]
    optional: true
```

### 3. 各種設定
設定ファイル「user-data」を編集し、各種設定を行う。
**ホスト名（rp401）、ユーザー名（s8ta）、SSH公開鍵（ssh_authorized_keys）の部分は要変更。**

```yaml:user-data
#cloud-config

# ホスト名設定
hostname: rp401

# ユーザー作成
users:
  - name: s8ta
    groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-rsa AAAABBBBCCCCDDDD...

# SSHパスワードログイン無効化
ssh_pwauth: false

# ロケール設定
locale: ja_JP.UTF-8

# タイムゾーン設定
timezone: Asia/Tokyo

# 一時ディレクトリのRAMディスク化
mounts:
  - [ tmpfs, /tmp, tmpfs, "defaults,noatime,size=256m,mode=1777", "0", "0" ]

# パッケージ更新
package_update: true
package_upgrade: true

# ファイアウォール設定・再起動
# SSHのみ許可
runcmd:
  - ufw limit ssh
  - ufw enable
  - reboot
```

#### 一時ディレクトリのRAMディスク化について
SDカードへの書き込みを減らし、寿命を延ばすために/tmpをRAMディスク化している。
/var/logも同様の理由でRAMディスク化したいが、単純に設定すると不具合が生じる可能性があるため、設定方法を下記記事にまとめた。
[ラズパイの/var/logを簡単にRAMディスク化](https://qiita.com/s8ta/items/9e08242e30ec7929fa89)

また、/var/tmpは再起動時にデータが削除されない想定のディレクトリのため、RAMディスク化していない。

### 4. SDカードをラズパイに差し込み、電源ON
cloud-initによる設定と再起動が完了するまで少し待つ。
参考までに、読込95MB/秒、書込20MB/秒のSDカードでは、初回の電源ONから再起動までに約12分かかった。
パッケージ更新の時間が非常に長いので、早めに動作確認したい場合は`user-data`のパッケージ更新部分をコメントアウト（先頭に#を追加）し、SSH接続後に手動で更新すると良い。
（可能ならディスプレイは接続し、設定状況を確認しながら作業すると安心。）

### 5. SSH接続・設定確認
ラズパイの再起動後、SSHで接続し、正しく設定されていることを確認する。

#### ホスト名の確認
```
$ hostname
rp401
```

#### ユーザー・所属グループの確認
```
$ id
uid=1000(s8ta) gid=1000(s8ta) groups=1000(s8ta),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),115(netdev),118(lxd)
```

#### SSHパスワードログイン無効の確認
```
$ grep 'PasswordAuthentication ' /etc/ssh/sshd_config
PasswordAuthentication no
```

#### ロケールの確認
```
$ locale
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
```

#### タイムゾーンの確認
```
$ timedatectl
               Local time: 日 2021-03-21 16:23:00 JST
           Universal time: 日 2021-03-21 07:23:00 UTC
                 RTC time: n/a                       
                Time zone: Asia/Tokyo (JST, +0900)   
System clock synchronized: yes                       
              NTP service: active                    
          RTC in local TZ: no
```

#### 一時ディレクトリのRAMディスク化確認
```
$ df -h | grep /tmp
tmpfs           256M     0  256M   0% /tmp
```

#### パッケージの更新確認
```
$ sudo apt update
ヒット:1 http://ports.ubuntu.com/ubuntu-ports focal InRelease
ヒット:2 http://ports.ubuntu.com/ubuntu-ports focal-updates InRelease
ヒット:3 http://ports.ubuntu.com/ubuntu-ports focal-backports InRelease
ヒット:4 http://ports.ubuntu.com/ubuntu-ports focal-security InRelease
取得:5 http://ports.ubuntu.com/ubuntu-ports focal/main Translation-ja [296 kB]
取得:6 http://ports.ubuntu.com/ubuntu-ports focal/universe Translation-ja [1,504 kB]
取得:7 http://ports.ubuntu.com/ubuntu-ports focal/multiverse Translation-ja [7,116 B]
1,807 kB を 4秒 で取得しました (475 kB/s)   
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています       
状態情報を読み取っています... 完了
パッケージはすべて最新です。
```

#### ファイアウォールの設定確認
```
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     LIMIT IN    Anywhere                  
22/tcp (v6)                LIMIT IN    Anywhere (v6)
```