概要
ラズパイ4にUbuntu 20.10をインストールしたという話。MicroHDMIを持っていなかったので、キーボードやディスプレイを接続せずに、インストールと初期設定を行います。
Ubuntuをインストールして、PCからSSHでログインできるようにしていますが、 Cloud-init(user-data)の仕組みを活用して、起動後の作業がなるべく発生しないようにしています。
以前の記事ではUbuntuのインストール、起動後にいろいろ設定が必要でしたが、その辺を自動化した手順となっています。:[Raspberry pi3] Ubuntu 18.04 LTS のインストール(キーボード、ディスプレイ不要)
用意するもの
Raspberry Pi 4 8GB RAM
ラズパイケース
USB Type-Cの電源
MicroSDカード 128GB
アルミ製のケースは見た目もオシャレで、ヒートシンクの役割もするので良いですね。トラブルがあったときに備えてMicroHDMIのケーブルもあったほうが良さそうです。
インストールした環境
Ubuntu Server 20.10 64bit (arm64)
RAM容量が増えてるので64bit版を選びます。
用途によっては Ubuntu Server 20.04.1 LTS (arm64) を選ぶのも良いですね。
Ubuntu のダウンロードとインストール
Raspberry Pi Imager を公式サイトからダウンロードして、作業用PCにインストールします。Raspberry Pi Imager は、OSのダウンロードからSDカードへの書き込みまでやってくれます。Raspbianだけでなく、UbuntuなどのOSにも対応しているすぐれものです。
Raspberry Pi Imagerを起動したら、Ubuntu Server 20.10 64-bit (arm64) と書き込み先のSDカードを選んで、「Write」をクリックするだけです。
しばらく待つとSDカードへの書き込みが完了します。以前までは自分でOSイメージと書き込みツールを用意する必要がありこの作業も面倒でした。
起動前の設定
まだRaspberryPiは使いません。UbuntuのOSイメージが書き込まれたSDカードをもう一度、作業用PCに差し込みます。
SDカードのSystem-bootにあるファイルに、事前設定を加えることで、初回の起動時から自宅サーバーとしての下地を作っておきます。
ネットワークの設定 : network-config
SDカードにある network-config というファイルを編集することで、あらかじめネットワークの設定をすることができます。私の環境では、ここにWIFIの設定(SSID、パスワード、固定IP、DNS、デフォルトゲートウェイ)を設定しました。有線LANを使う場合は、eth0を固定IPにすれば良いかと思います。
(公式ドキュメント) https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html
# network-config の設定例
version: 2
ethernets:
eth0:
# Rename the built-in ethernet device to "eth0"
match:
driver: bcmgenet smsc95xx lan78xx
set-name: eth0
dhcp4: true
optional: true
wifis:
wlan0:
access-points:
MYWIFI-SSID:
password: "MYWIFI-PASSWORD"
addresses:
- 192.168.68.20/24
gateway4: 192.168.68.1
nameservers:
addresses:
- 192.168.68.1
dhcp4: no
dhcp6: no
optional: true
ネットワークに詳しくない人は、DHCP + 有線LAN が敷居が低いです。
ただ、モニタがないとラズパイに割り当てられたIPアドレスが簡単にわからないので、user-data のパッケージインストールのところで、avahi-daemon を入れしまうと良いかもしれません。そうしておけば、IPアドレスがわからなくても、「ホスト名.local」(例:pi4.local)でアクセスできるようになります。
## パッケージのインストール
packages:
- emacs-nox
- avahi-daemon
初期設定 : user-data
今回は user-data を使って以下の設定を行いました。
ホスト名をセット:pi4.your.hostname
タイムゾーンを”Asia/Tokyo”にセット
ロケールを”ja_JP.UTF-8″にセット
SSHのパスワードでのログインを禁止
デフォルトユーザ(ubuntu)は作成しない
自分用のユーザ(myuser)を作成
SSHの公開鍵をインポート(.ssh/authorized_keysに書き込む)
Emacsをインストール
SDカードの延命措置(/tmp、/var/tmp、/var/logのRAMDISK化)
Dockerをインストール
ファイアウォールの設定
#cloud-config
の設定例
# ホスト名の設定
hostname: pi4.your.hostname
# タイムゾーン、ロケールの設定
timezone: "Asia/Tokyo"
locale: "ja_JP.UTF-8"
# SSH でのパスワードログインを禁止
ssh_pwauth: false
# グループの作成
groups:
- docker
# ubuntuユーザの作成を止めて、自分用ユーザーを作る。複数ユーザ作りたい場合は、-name 以下をユーザ分追記する。
users:
# - default # ここのコメントを外すと、デフォルトユーザ(ubuntu)が作られます。
- name: myuser
gecos: I am an user.
primary_group: myuser
groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
# パスワードログインは使わない
lock_passwd: true
# githubのアカウントに設定してある公開鍵をインポートする(とても便利!)
ssh_import_id:
- gh:my_github_account
# githubに設定していない場合は、直接公開鍵を書いておけば良い。
# ssh_authorized_keys:
# - ssh-rsa AAAAB3NzaC1yc2EXXXXXXXXXXXXXXXXXXXXXXXXXXXX
## 初回起動時にパッケージのアップデートを行う。お好みで設定する。
#package_update: true
#package_upgrade: true
## パッケージのインストール
packages:
- emacs-nox
# - avahi-daemon # pi4.local みたいな感じで名前解決ができる
## サーバー用途ではSDカードがすぐ壊れるので、RAMDISKを使って対策をする
## /tmp,/var/tmp,/var/logをRAMDISK化する
mounts:
- [ tmpfs, /tmp, tmpfs, "defaults,size=256m", "0", "0" ]
- [ tmpfs, /var/tmp, tmpfs, "defaults,size=256m", "0", "0" ]
- [ tmpfs, /var/log, tmpfs, "defaults,size=128m", "0", "0" ]
## Docker のインストールとfirewallの設定をする
## Docker はお好みで。Firewall は必須。
runcmd:
- apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
- add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- apt-get update -y
- apt-get install -y docker-ce docker-ce-cli containerd.io
- ufw limit ssh
- ufw enable
ラズパイを起動する
SDカードをラズパイにさしたら電源を入れましょう。数分待てばラズパイが使用できるようになります。SSHでログインできたらOKです。設定例に書いた User-data だとdockerのインストールも行なっているので、cloud-init の final ステージが終わるまでに10分程度かかりました。
.ssh/authorized_keys に公開鍵がセットされていますし、ufwの設定もされています。デフォルトの ubuntu ユーザは作られなくなりました。
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp LIMIT Anywhere
22/tcp (v6) LIMIT Anywhere (v6)
最初からRAMDISKも使われています。
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 782M 20M 762M 3% /run
/dev/mmcblk0p2 116G 3.5G 107G 4% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup
tmpfs 256M 0 256M 0% /tmp
tmpfs 128M 660K 128M 1% /var/log
tmpfs 256M 0 256M 0% /var/tmp
/dev/mmcblk0p1 253M 153M 100M 61% /boot/firmware
tmpfs 782M 4.0K 782M 1% /run/user/1000
user-data についての補足
お勧めはしませんが、SSHでパスワードログインを行いたい場合は、user-dataは以下の設定をします。
# パスワードの
変更
chpasswd:
expire: false
list:
- myuser:MYUSER_PASSWORD
# SSHのパスワード認証を有効にする
ssh_pwauth: true
あと、ssh_import_idで、githubの公開鍵をインポートする場合、下記のURLで自分の公開鍵が見れます。公開鍵にアクセスできるかどうか、事前にチェックしておくと良いでしょう。
https://api.github.com/users/kitter11/keys
(アカウントkitter11のところは自分のGITHUBIDに置き換えてください。)
github等の仕組みが使えない場合は、ssh_import_id の部分を消して、代わりにssh_authorized_keys に直接公開鍵を書いてしまえばOKです。
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EXXXXXXXXXXXXXXXXXXXXXXXXXXXX
cloud-config(user-data)のデバッグ
user-dataの設定については、下記の公式ドキュメントを見て追記・変更をしました。
https://cloudinit.readthedocs.io/en/stable/topics/examples.html
https://cloudinit.readthedocs.io/en/latest/topics/modules.html
user-dataのトライ・アンド・エラーのやり方
cloud-initについて、知識がなかったので、設定が固まるまではトライ・アンド・エラーの繰り返しでした。自分は下記の順序で設定を作りました。
・ネットワークの設定だけは済ませて、ラズパイにログインできるようにしておく。とりあえずはubuntu/ubuntuでも良い。
・公式ドキュメントで、できそうなことを調べる
・ラズパイにログインしてからもuser-data はいじれるので、適宜編集する。
$ sudo vi /boot/firmware/user-data
・cloud-initをリセットする。
$ sudo cloud-init clean
$ cloud-init status
status: not run
・cloud-init を再実行する。
$ sudo cloud-init init
$ sudo cloud-init modules --mode config
$ sudo cloud-init modules --mode final
cloud-init には、init/config/final の3つのステージがあり、各ステージは別々に実行することができます。どのステージでどのモジュールが実行されるかは、/etc/cloud/cloud.cfg で定義されています。
# init で実行されるモジュール
cloud_init_modules:
- migrator
- seed_random
- bootcmd
- write-files
- growpart
- resizefs
- disk_setup
- mounts
- set_hostname
- update_hostname
- update_etc_hosts
- ca-certs
- rsyslog
- users-groups
- ssh
# cloud-init modules --mode config で実行されるモジュール
# The modules that run in the 'config' stage
cloud_config_modules:
# Emit the cloud config ready event
# this can be used by upstart jobs for 'start on cloud-config'.
- emit_upstart
- snap
- ssh-import-id
- locale
- set-passwords
- grub-dpkg
- apt-pipelining
- apt-configure
- ubuntu-advantage
- ntp
- timezone
- disable-ec2-metadata
- runcmd
- byobu
# cloud-init modules --mode final で実行されるモジュール
# The modules that run in the 'final' stage
cloud_final_modules:
- package-update-upgrade-install
- fan
- landscape
- lxd
- ubuntu-drivers
- puppet
- chef
- mcollective
- salt-minion
- reset_rmc
- refresh_rmc_and_interface
- rightscale_userdata
- scripts-vendor
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- phone-home
- final-message
- power-state-change
・うまく行かなかったら /var/log/cloud-init.log を見る
まとめ
電源を入れば、基本設定の済んだUbuntuが使えるようになりました。いままでインストール後にゴニョゴニョしていた作業がなくなりとても便利です。
cloud-init は汎用的な仕組みなので、AWSでの運用にも応用ができると思います。
ぜひお試しください。
今回使った設定ファイルはGithubに。https://github.com/kitter11/RaspberryPi
pi3のときには、インストール後の作業が盛りだくさんだったのに、ずいぶんとスッキリしたな。次はDockerでWordpressやPostfixなどを立ち上げてラズパイ4をメインの自宅サーバーへ置き換えるべし。
avahi-daemon も最初に入れちゃえば、DHCPでもとりあえずホスト名でアクセスできるようになるのかなぁ。試してみるべし。
コメント