Raspberry Pi 3 Model B+ で Ubuntu Server 16.04 を使う方法

# はじめに
Raspberry Pi で Ubuntu を使いたい時，まず思いつくのは Raspberry Pi 3 Model **B** で使える [Ubuntu MATE](https://ubuntu-mate.org/raspberry-pi/) だと思います．

しかしながら，Raspberry Pi 3 Model **B+** では Ubuntu MATE は使えないようです．

3B+で [ROS Kinetic](https://wiki.ros.org/kinetic/) を使いたい際に，どうしたら良いのか調べてみたら，Ubuntu Server なら3B+で使えるという記事がいくつかあったので，それらを参考にしてイメージを用意する手順をまとめてみました．

## 作業した環境
 - Ubuntu 16.04.5 LTS
 - microSDカードリーダーライター

# 手順
## 1. Raspberry Pi 2用のイメージをダウンロード
[cdimages.ubuntu.com](http://cdimage.ubuntu.com/ubuntu/releases/xenial/release/) から [ubuntu-16.04.4-preinstalled-server-armhf+raspi2.img.xz](http://cdimage.ubuntu.com/ubuntu/releases/xenial/release/ubuntu-16.04.4-preinstalled-server-armhf+raspi2.img.xz) をダウンロードする

## 2. Etcher や dd コマンドを使ってSDカードにイメージを焼く（どちらかで焼いて下さい）

- [Etcher](https://etcher.io/)

> Validated Flashing, Hard Drive Friendly, Beautiful Interface, Open Source, Cross Platform, More on the way
　　

　　Etcherという，イメージを焼くのに適したソフトがあります．　　
　　使い方は難しくありません．xzを解凍する必要はありません．　　
　　1. `Select image` で 落としたイメージを選択します．　　
　　2. `Select drive` で PCに挿したSDカードを選択します．　　
　　3. `Flash!` でパスワードを要求されるので入力します．　　


- [dd](https://www.ibm.com/support/knowledgecenter/ja/ssw_aix_71/com.ibm.aix.cmds2/dd.htm) コマンド

 1. イメージを解凍する  

    ```
    cd [イメージがあるディレクトリ]
    ```

    ```
    unxz ubuntu-16.04.4-preinstalled-server-armhf+raspi2.img.xz
    ```  
 2. イメージを焼く  


    ```
    dd bs=4M if=ubuntu-16.04.4-preinstalled-server-armhf+raspi2.img of=/dev/sdX status=progress conv=fsync
    ```  

sdX は環境に合わせて変えてください．

## 3. disk 拡張の準備をする
```
sudo fdisk /dev/sdb
```
/dev/*** は環境に合わせて変えてください．

```
p  # sdb2 の Start の値 をメモしておいてください．
d  # delete
2  # 2番目を選択
p  
n  # new
p  # Primary
2  
270336 # sdb2 の Start の値
[Enter Key]
p  
w  # 保存して終了
```
起動後に`resize2fs /dev/mmcblk0p2`を行う

## 4.  [raspberrypi/firmware](https://github.com/raspberrypi/firmware.git) をクローンする
```
git clone https://github.com/raspberrypi/firmware.git
```

## 5. クローンしたリポジトリの一部をSDカードの指定の位置へコピーする（上書き）
SDカードをPCが認識していない時は抜き差ししてみてください．  
SDカードは以下のように見えていると思います．

```
/media/[ユーザ名]/cloudimg-rootfs
/media/[ユーザ名]/system-boot
```
余談 ：
本当はMac OSでイメージを作成したかったけど，`cloudimg-rootfs` がマウントできていないみたいだった．VMWare Fusion上のUbuntuでは見えた．

```
sudo cp -rip [クローンしたfirmware]/boot/* /media/[ユーザ名]/system-boot/
```

```
sudo cp -rip [クローンしたfirmware]/modules/* /media/[ユーザ名]/cloudimg-rootfs/lib/modules/
```

- cp のオプション
  - r : 再帰的にコピー（ディレクトリ）
  - i : 上書きを確認
  - p : パーミッションなどを保持

i オプションは念のため．`cp: overwrite ~ ?` は Enter key で実行．

## 6. system-boot 内の config.txt を修正する
```
sudo nano /media/[ユーザ名]/system-boot/config.txt
```
おそらく，5~6行目くらいに

```
kernel=uboot.bin
device_tree_address=0x02000000
```
という行があるので，`kernel=uboot.bin`を消すかコメントアウトして

```
device_tree_address=0x02000000
```
となるようにする．

## 7. flash-kerne/db/all.dbへ追記する
```
sudo nano /media/[ユーザ名]/cloudimg-rootfs/usr/share/flash-kernel/db/all.db
```
下記の内容を一番下へ追記する．  

```
Machine: Raspberry Pi 3 Model B Rev 1.2
Kernel-Flavors: rpi2 rpi2-rpfv
DTB-Id: bcm2710-rpi-3-b.dtb
Boot-Kernel-Path: kernel7.img
Boot-DTB-Path: bcm2710-rpi-3-b.dtb
Boot-Device: /dev/mmcblk0p1

Machine: Raspberry Pi 3 Model B Plus Rev 1.3
Kernel-Flavors: rpi2 rpi2-rpfv
DTB-Id: bcm2710-rpi-3-b-plus.dtb
Boot-Kernel-Path: kernel7.img
Boot-DTB-Path: bcm2710-rpi-3-b-plus.dtb
Boot-Device: /dev/mmcblk0p1
```

## 8. boot を整理する

```
cd /media/[ユーザ名]/cloudimg-rootfs/boot/
```

```
sudo rm -rf v* r* i* g* c* a* S* firmware.bak/
```

## 9. オンボードの無線LANを使えるようにする
```
cd /media/[ユーザ名]/cloudimg-rootfs/lib/firmware/brcm/
```

```
sudo wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.bin https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.clm_blob https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.txt
```

## 10. root のパスワードを初期化する
```
sudo nano /media/[ユーザ名]/cloudimg-rootfs/etc/shadow
```
1行目の

```
root:*:17590:0:99999:7:::
```
を

```
root::17590:0:99999:7:::
```
へ書き換える．

## 11. A start job is running for raise network interfaces 対策
これをしないかつ，有線LANが刺さってない場合は5min待たされる．

```
rm /media/[ユーザ名]/cloudimg-rootfs/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online  
mv /media/[ユーザ名]/cloudimg-rootfs/etc/systemd/system/cloud-init.target.wants /media/[ユーザ名]/cloudimg-rootfs/root/
```

```
sudo nano /media/[ユーザ名]/cloudimg-rootfs/etc/network/interfaces.d/eth0
```

```
allow-hotplug eth0
  iface eth0 inet dhcp
```
下は無線LANのNIC起動

```
sudo nano /media/[ユーザ名]/cloudimg-rootfs/etc/network/interfaces.d/wlan0
```

```
auto wlan0
  iface wlan0 inet dhcp
```


interfaces に interfaces.d の設定を読み込む設定を書く

```
sudo nano /etc/network/interfaces
```

```
source-directory /etc/network/interfaces.d/
```

メモ :  
`auto eth0` だと、ブート時にネットワーク接続を確認し始めるため，接続されてないと 5min wait... になります．

5min は` (/media/[ユーザ名]/cloudimg-rootfs)/etc/systemd/system/network-online.targets.wants/networking.service` で指定されています．このファイルの `TimeoutStartSec=5min` を `TimeoutStartSec=5sec` に書き換えれば 5秒 wait で済みますが，ブート後，`sudo service networking status` とか見ると error が出る可能性があります．

`allow-hotplug eth0` にすると、有線が刺さしたときに接続を確認するらしいので，auto でなく allow-hotplug を使うと wait... がなくなり error も出ないはずです．

## 12. GPUファームウェアを更新
[raspberrypi-firmware](http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/) から新しそうなブートローダーをダウンロードしてください．

```
wget http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-bootloader_1.20180703-1_armhf.deb
```

```
mkdir pi-bootloader
```

```
dpkg-deb -x raspberrypi-bootloader_1.20180703-1_armhf.deb pi-bootloader
```

```
cp -p pi-bootloader/boot/* /media/[ユーザ名]/system-boot/
```

---

ここまでで起動はできるはずです．  
Raspberry Pi 3 Model B+ に SDカードを挿して，モニタ・電源・キーボードを接続しましょう．

電源を入れる前に モニタ へ接続しましょう．  
電源を入れてからモニタを接続しても出力されません．

---
## ログイン【起動後】

```
ubuntu login:
```
と出たら

```
root
```
と打ちましょう．

## root のパスワード設定【起動後】
```
passwd root
```
root にパスワードを設定してあげてください．

## ディスク拡張【起動後】
```
resize2fs /dev/mmcblk0p2
```
前後で `df -h` すると違いがわかるかも．

## ユーザ作成 と sudo へ追加【起動後】
```
adduser [ユーザ名]
```

```
gpasswd -a [ユーザ名] sudo
```

ROSを使う人は `pi` とかにしておくと幸せかもしれない．

## ホスト名解決【起動後】
これをせずに，ユーザを作成した後に `sudo` を使うと

```
sudo: unable to resolve host
```
みたいのが毎回出ます．

```
sudo nano /etc/hosts
```
へ

```
127.0.1.1 ubuntu
```
を追記してください．

## Ubuntuの無線LANの電源管理をオフにする【起動後】
```
sudo apt install wireless-tools
```

```
sudo nano /etc/rc.local
```
に以下を追記してください．

```
sbin/iwconfig wlan0 power off
```

## Ubuntu16.04 の IP固定【起動後】
もし起動後すぐ `ssh` で作業したい場合は 11. で interfaces.d のファイルを作成した時に固定しよう．

```
allow-hotplug eth0
  iface eth0 inet static
  address 192.168.x.x
  netmask 255.255.255.0
  gateway 192.168.x.1
  dns-nameservers 8.8.8.8 192.168.x.1
```
## Ubuntu16.04 の無線LAN設定【起動後】
```
sudo apt install wpasupplicant
```

```
su -
wpa_passphrase [ESS-ID] [PASSPHRASE] > /etc/wpa_supplicant/hoge.conf
```
もしネットワークがステルスAPだったら

```
sudo nano /etc/wpa_supplicant/hoge.conf
```
に

```
scan_ssid=1
```
を追記する．

```
sudo nano /etc/network/interfaces.d/wlan0
```

```
auto wlan0
  iface wlan0 inet dhcp
  wpa-conf /etc/wpa_supplicant/hoge.conf
```

を追記したら再起動しましょう．

## service ssh status で鍵関係で怒られた場合
```
sudo dpkg-reconfigure openssh-server
```

## ssh_config と sshd_config
クライアントがssh，サーバーがsshd  
アクセスされるポートを変更したい場合は `sshd_config` をいじる．

## NICの状態を確認するコマンド
```
sudo lshw -c network
```

# Mac OS での image のバックアップ方法
- バックアップ

```
sudo dd if=/dev/rdiskX of=bk.img bs=1m
```
- xzに圧縮

```
tar Jcvf output.tar.xz input.img
```

# まとめ
Raspberry Pi 3 Model B+ で Ubuntu を使いたい状況に陥ったので，動いてよかったです．

もし誤った情報を記載していたらコメントいただけると幸いです．

# 参考
- [RaspberryPi | ubuntu wiki](https://wiki.ubuntu.com/ARM/RaspberryPi)
- [RaspberryPi 3B+でUbuntu 16.04を起動させる方法【単体セットアップ】 | ASRobot](https://www.asrobot.me/entry/2018/07/11/001603)
- [Raspberry Pi 3 B+にUbuntu desktop18.04 をインストールする | Qiita](https://qiita.com/y_sk256/items/5fb7124e178615be11a2)