Raspberry Pi 3/4にUbuntuをインストール

# 概要
Ubuntu Server/Desktopのインストールについての説明．
このページは[Ubuntu Serverのインストール](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)がメイン．素直にDesktopをインストールする場合は，[UbuntuのRaspberry Piページ](https://ubuntu.com/download/raspberry-pi)のトップの位置あたりにある「[desktop](https://ubuntu.com/tutorials/how-to-install-ubuntu-desktop-on-raspberry-pi-4#1-overview)」を選択してtutorialを見た方がよい．

## モチベーション
ROS2の少人数ゼミを行うときに，PC使うのではなくRaspberry Pi使った方が

* 安上がりじゃないか？
* ハードウェア扱うのに接続性が良くないか？
* 面白いんじゃない？

と思ったから．

## ネットワーク環境の変動に対する考え方
raspberry piの場合，使用状況が色々変わる．持ち運びも考慮に入る．これにより状況によってネットワーク環境が変わることが想定される．ROSで遊ぶならDNS/DHCPなくても扱えるようにしたい．

### 無線LANの場合
無線LANで接続できる場合，IPが自動で割り振られる状況のみを想定する．IPが自動で割り振られない場合，そもそも無線サービスが使えないと考え，IPが割り振られれず利用できないままにしておく．

* 対処
    * ネットワーク設定にてdhcpによる割り振りを行う(netplanのyaml設定ファイルでdhcp4: trueとする)．
    * IPが変わる可能性があるので，ssh接続などは名前解決で行う．dnsがない可能性も考え，avahi-daemonによる名前解決を行う．

### 有線LANの場合
有線LANの場合，以下の状況が考えられる．

1. LANケーブルが刺さっていない
1. dhcpサーバによりIPが自動で割り振られる
1. dhcpサーバのないネットワークに接続しちゃった
1. 固定IPを設定しなければならないネットワークである

このうち，4.は考えず，1.から3.で適当にIP割り振っちゃっていい状況を対象とする．
わりとraspberry piを持ち運んだりして状況が変わると，1.になったり2.になったり途中で状況が変わるけど，それでも動くようにしたい．

* 対処
    * link-localによるプライベートIPの自動割り振り(169.254.0.0/16)を行う(netplanのyaml設定ファイルでlink-local: [ipv4]を使う)
    * avahi-daemonによる名前解決を行う(無線LANと同じ)

# Ubuntu Serverのインストール・設定
## microSDカードへのインストール
[UbuntuのRaspberry Piページ](https://ubuntu.com/download/raspberry-pi)が充実している．このページの「Download Ubuntu Server」や「Download Ubuntu Desktop」からダウンロードしても良いが，トップの位置あたりにある「[desktop](https://ubuntu.com/tutorials/how-to-install-ubuntu-desktop-on-raspberry-pi-4#1-overview)や[server](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)」を選択してtutorialを見た方がよい．ここでは[server](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)を選択．

### Raspberry Pi Imagerによるインストール方法
[server](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)通りに実行．特に気を付けるところは以下の通り．

[Raspberry Pi Imager for Windows](https://downloads.raspberrypi.org/imager/imager_latest.exe)にて．Mac, Unixは[server](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)に説明あり．

* CHOOSE OS
    * Other general purpose OS
        * Ubuntu ServerLTS(RPi 3/4/400) 64bit版のお好きなバージョンを選択
* 右下の歯車マークで事前に色々設定可


## Ubuntu Serverの設定
### 起動・ログイン

microSDカード，HDMI，キーボード/マウスをつなげてRaspberry Piを起動すると普通のUbuntuインストールとなる．まずは普通のインストールを終わらせる．

最初の起動後，ID・パスともにubuntuでログインするかSDカードへの書き込み時に設定したID・パスでログインする．
ただ，最初は種々の設定を書き込む時間が必要で，すぐにログインできないかもしれない．数分待って画面半分くらいになんかメッセージが出たらログインできるようになる．

### ネットワーク関連設定
#### 基本設定
普通のインストール後に追加で設定．

* 設定ファイル
    * /etc/netplan/50-cloud-init.yaml
* 今回の例
    * 有線・無線ともにDHCPにて自動割り当て
    * 無線LANのssidをmyssid，セキュリティキーをmypassとして説明するので適宜自分用に読み替え
    * renderer: networkdを使用[^renderer_link-local]


```50-cloud-init.yaml
network:
    version: 2
    renderer: networkd
    ethernets:
        eth0:
            dhcp4: true
            dhcp6: true # 使わないならfalse
            link-local: [ ipv4, ipv6 ] # v6いらないなら [ ipv4 ]でおけ
    wifis:
        wlan0:
            dhcp4: true
            dhcp6: true # 使わないならfalse
            access-points: # 複数のssidを登録可
                "myssid":
                    password: "mypass"
```

設定後，以下のコマンドでネットワーク設定の有効化．

```Bash:terminal
$ sudo netplan apply
```

非公開SSIDへの接続，パスワードの暗号化などは以下が参考となる．

* [Raspberry Pi 4 (Ubuntu Server 20.04.1 LTS ) で非公開SSIDのアクセスポイントに接続する](https://qiita.com/cocoabreak/items/6967ad16cd7583b3189c)

#### avahi-daemon[^avahi]

```Bash:terminal
$ sudo apt install avahi-daemon
$ sudo systemctl enable avahi-daemon
$ sudo systemctl start avahi-daemon
```

- /etc/hostnameで名前を指定[^hostnamectl]
 - 同じネットワーク内で名前が被らないように気を付ける
 - 以下はとりあえずの例

```:/etc/hostname
pi001
```

これでホスト名.localでアクセス可能となる．この例の場合，pi001.localでアクセスできるようになる．
注意点として，ホスト名の中に`.`(ピリオド)は使えない．例えば，pi.001とはできない(pi.001.localでアクセスできない)．

### その他通常の設定
#### 念のため
入っていると思うが念のためインストール

```shell
$ apt install ssh git
```

#### hostnameの設定

```shell:設定
$ sudo hostnamectl set-hostname [コンピュータ名]
```

```shell:一時的な設定(再起動すると元に戻る)
$ hostname [コンピュータ名]
```

```shell:確認
$ cat /etc/hostname
```


#### 時刻合わせ
- 設定ファイル編集

```:/etc/systemd/timesyncd.conf
NTP=ntp.nict.jp
FallbackNTP=ntp.ubuntu.com # 複数指定する場合にはスペース区切りで続けて記述
```

```Bash:terminal
$ timedatectl set-ntp true
$ sudo systemctl enable systemd-timesyncd.service
$ sudo timedatectl set-timezone Asia/Tokyo
$ sudo systemctl restart systemd-timesyncd.service
```

#### ロケール・キーボード・スワップファイルの設定
[ここ](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0564)を参考．

```Bash:terminal
$ sudo locale-gen ja_JP.UTF-8
$ sudo dpkg-reconfigure -f noninteractive locales
$ echo "LANG=ja_JP.UTF-8" | sudo tee /etc/default/locale
```
/etc/default/keyboardを編集
- XKBMODEL="jp106"にする
- XKBLAYOUT="jp"にする

スワップファイルはメモリの使用状況をみて必要なら行う．

```Bash:terminal
$ sudo fallocate -l 1g /swapfile
$ sudo chmod 600 /swapfile 
$ sudo mkswap /swapfile 
$ echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
$ sudo swapon -a
```

2行目で1GBのスワップファイルを作成している．

#### システムアップデート[^system_update]

```Bash:terminal
$ sudo apt update && sudo apt upgrade
```

## Tips
* Atomを使ってリモートでRaspberry Pi上のファイルを編集・実行
    * [RaspberryPi内のPythonファイルをAtomのリモート機能で編集したら最高だった](https://qiita.com/G-san/items/833c2b0e92e9c0b9dfa2)

# デスクトップ環境のインストール
## 注意
もしDesktopのバージョンの問題(特定のバージョンが手軽にインストールできない等)がある場合，

1. Ubuntu Serverをインストール
1. デスクトップ環境(xubuntu)をインストール

と段階的に行う．この場合は以下の手順を参考に．
もし問題がなく，インストールしたいDesktop環境が[Raspberry Pi Imager for Windows](https://downloads.raspberrypi.org/imager/imager_latest.exe)でインストールできなるのであれば，[チュートリアル通り](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi)に進めた方がよい．

## 段階的に行う場合の話
デスクトップ環境はひとつのアプリケーションなので色々インストールできる．[server](https://ubuntu.com/tutorials/how-to-install-ubuntu-on-your-raspberry-pi#1-overview)の5. Install Desktopから選択できるものを紹介しているblogなどに飛べる．ちょっと紹介文が面白い．
ここではxubuntuを選択．

```shell
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install xubuntu-desktop
```

## xubuntuインストール途中の選択

* ディスプレイマネージャ
    * gdm3
    * LightDM
        * こっちの方がいいかな？

## ディスプレイマネージャの変更

```shell
$ sudo dpkg-reconfigure gdm3
```

もしかしたら以下をやるようにメッセージが出るかもしれない．その場合には実行

```shell
$ sudo dpkg --configure lightdm
```

# その他
## SDカードのイメージ作成・復元
何台ものRaspberry Piを複数の人(学生)が同じ(ような)環境で使いたい場合，いちいちインストール・設定をするのは面倒．
そこで原初のSDカードを作成後，バックアップ(イメージの作成・保存)と復元(イメージからSDカードの作成)を考える．
ソフトウエアは[Win32DiskImager](https://freesoft-100.com/review/win32diskimager.html)を使用する．リンクからDLしてもよし，以下のコマンドでいれても良し．

```terminal: windows terminal
winget install --id Win32diskimager.win32diskimager
```

### 初手
必要なソフトウエアは全部入れておく．
raspberry pi上でavahi-daemonをdisableにしておく．

```bash:raspberry pi terminal
$ sudo systemctl disable avahi-daemon
```

その後電源落として，raspberry piからWindowsにSDカードを挿し替える．

### SDカードのバックアップ(イメージ作成)・復元
有名なソフトなので「Raspberry Pi SDカード バックアップ 復元」などで沢山情報得られる．

### 後処理
以下について行う．

* raspberry piに挿し替えて起動
* パーティションの拡張
    * Win32DickImagerで復元したらそのまま最大容量まで使えていた．もし使えていないケースの場合，次の[SDカードの未使用領域の拡張方法について](https://armadillo.atmark-techno.com/forum/armadillo/8702)が参考になるかも？
* hostnameの変更
    * avahi-daemonを使用するので固有の名前をつける必要があるので必須
* avahi-daemonの有効化
    * 識別のためのhostnameを設定した後にavahi-daemonを有効化

```bash: raspberry pi terminal
$ sudo hostnamectl set-hostname [コンピュータ名]
$ sudo systemctl enable avahi-daemon
$ sudo systemctl start avahi-daemon
```

## 長期運用のための工夫

- [Raspberry PiのSDカードが壊れた！寿命を延ばす方法 5+1選!【運用編を追加】](https://iot-plus.net/make/raspi/extend-sdcard-lifetime-5plus1/)



[^armhf_arm64]: ここで使用したのは64bitだけど，Raspberry Piではまだまだ32bitがメインらしい([新しい地図](https://ameblo.jp/mongol-sky/entry-12413849956.html))．

[^login_with_ssh]: この時点でsshによるログイン可能となる．

[^netplan]: Ubuntu 18.04なのでLANの設定はnetplanの形式となる．詳しくは[公式](https://netplan.io/)のmenuからreferenceやexampleが参考になる．

[^renderer_link-local]: netplanの場合，rendererにnetworkdとNetworkManagerを選択できる．しかしNetworkManagerの場合，dhcp4: trueにするとlink-localのオプションが無効化されてしまう([netplan referenceのlink-localの項](https://netplan.io/reference))．よってlink-localのオプションを使う場合，networkdにしないといけない．

[^avahi]: dhcp割り当てなのでIPが変わる可能性があり，IPによるssh接続は面倒となる．そこでホスト名による接続のためavahi-daemonを使う([手持ちのRaspberryPiをサクッとmDNSに対応させる](https://qiita.com/takish/items/1a640576caa2d0dfefc4))．

[^hostnamectl]: 有効化のためのリブートが面倒ならhostnamectlコマンド使おう([server world](https://www.server-world.info/query?os=Ubuntu_16.04&p=hostname))

[^system_update]: 本当はインストール直後にも行う．というか隙あらば行う．