Ubuntuはデスクトップ向け・サーバー向けだけでなく、IoT向けの用途にも注力しています。その中核となるのが、普通のLinuxディストリビューションとは異なる「Ubuntu Core 」です。今回はRaspberry PiにUbuntu Coreをインストールして、その片鱗を味わってみましょう。
SnappyとかSnapとか言われてきたUbuntu Core
もともと「Ubuntu Core」は「Snappy Ubuntu Core」と呼ばれていた時期がありました。「 Snappy」はUbuntuがまだ「第三のモバイルOS四天王」の一角を占めていたころに登場した仕組みで、Ubuntu Phoneの開発で得られた知見を元に、よりIoT・コンテナ向けのシステムを構築するためのプラットフォームとなることが目的でした。
当時の「目論見」の詳細はUbuntu Weekly Topicsの2014年12月12日号 に詳しくまとまっています[1] 。無事に実現されたもの、いろいろあって諦めたものなどいろいろありますので、今一度当時の様子を確認して比較してみても良いでしょう。さらに登場して1年ぐらい経ったあとの第392回「Snappy Ubuntu Coreを試してみる 」ではいくつかの仮想マシンやクラウドサービス上でSnappyのインストール・利用方法を紹介しました。
[1] Snappyが登場した時点で「Ubuntu Core」という名前はすでに別の用途使われていました。当時のUbuntu Coreは「最低限aptコマンドでパッケージをインストールできる、Ubuntuとしての最小のルートファイルシステム」をアーカイブしたデータを意味していたのです。旧Ubuntu Coreは、現在では「Ubuntu Base 」という名前になって引き続き活用されています。
その後、コマンド名やパッケージフォーマット名がsnappyからsnapに変わったあたりで「Snappy」とは呼ばれなくなり、snapパッケージ自体が通常のシステムでも活用されるようになったあたりで単なる「Ubuntu Core」と呼ぶようになり、サイトもsnapパッケージのビルドツールに合わせて「snapcraft.io」となったりと、名前もいろいろと変遷しています。
現在は次のように名前を使い分けているようです。
Ubuntu Core :IoT向けにsnapベースで構築したUbuntuシステムの総称。ベースシステムのバージョンに合わせて「Ubuntu Core 18(UC18) 」と表現することも。
core18 :ベースシステムのバージョン名であり、システム自体のsnapパッケージでもある。Ubuntu 18.04 LTSベースなら「core18」 、Ubuntu 20.04 LTSベースなら「core20」となる。
snap :Ubuntu Coreで採用されているパッケージ管理システムであり管理用のコマンド。
snapd :snapパッケージを管理するデーモン。実質snapシステムの要石であり、snapdさえ一貫性が保たれていたら、core18とcore20をひとつのシステムで共存させることも可能。
Snap Store :snapパッケージの公式リポジトリ。独自ブランドのリポジトリを構築する方法も用意されている。
snapcraft :snapパッケージをビルドするためのツールであり、アプリ開発者向けのポータルサイト。
2020年12月時点での最新版はUbuntu 18.04 LTSベースのUbuntu Core 18です。Ubuntu 20.04 LTSベースのUbuntu Core 20 (UC20)は現在開発中で、間もなくリリースされる見込みとなっています。UC20ではインストーラーの改善、より大規模デプロイに向けたMAASやcloud-initのサポート、ディスク全体の暗号化などに対応する予定です。
Raspberry PiにUbuntu Coreをインストールする
Ubuntu CoreはIoT向けを名乗るだけあって、Raspberry Piのサポートを最重要視しています。本連載でも何度か紹介してる、Raspberry Pi Imager を使えば簡単にSDカードにUbuntu Coreをインストールできます。
Ubuntu Coreの選択肢は次の2種類です。
armhfアーキテクチャーの32bit版システム:Raspberry Pi 2/3/4、CM3に対応
arm64アーキテクチャーの64bit版システム:Raspberry Pi 3/4、CM3に対応
Raspberry Pi 2を使うならarmhfを、Raspberry Pi 3以降ならarmhf/arm64どちらか好みのほうを選択してください。ちなみにARMv6以前のRaspberry Pi 1やZeroには対応していません。
まずはRaspberry Pi Imagerをインストールします。
$ sudo snap install rpi-imager
「Super + A」などでアプリケーション検索画面から「raspberry」で検索すると「Imager」とラベルの付いたアイコンが表示されるはずです。それがRaspberry Pi Imagerですのでそれを起動してください。あとはRaspberry Pi用のSDカードを接続した上で次の手順でインストールします。なお、SDカードは最低でも4GiB以上、できれば8GiB以上のほうが良いでしょう。
図1 Operating Systemでは「Ubuntu Core」を選択
図2 Raspberry Pi用のSDカードを指定したら「WRITE」ボタンを押す
図3 しばらく待てば書き込みが完了する
あとは作成したSDカードをRaspberry Piに接続して起動するだけです。ちなみに「普通にインストールする」なら最低でも次の機材・アカウントが必要になります。
HDMIディスプレイとHDMIケーブル
LANケーブル
USB接続のキーボード
Ubuntu One アカウント
Ubuntu Coreをインストールするためには、Ubuntu Oneアカウントが必要になります。未取得の場合はあらかじめ作成しておいてください。また、アカウント作成後はこちらのページ からSSHの公開鍵を登録しておきましょう。Ubuntu Coreのシステムには、「 ネットワーク経由のSSH公開鍵を利用したログイン」のみが可能です。
なぜインストールだけで、アカウントが必要なのでしょうか。まず最初に、Ubuntu Coreは「Secure by Default」なシステムを目指しています。その一環として、従来のLinuxでは普通にできていたことも制約することで、よりセキュアなシステムを実現しようとしています。
たとえばIoTなデバイスはPCと異なり「マシンの目の前に正規の管理者が居る」ことは少なく、さらにサーバーのように「物理マシンにアクセスできる人は限定されている」わけでもありません。このため「コンソールからのログイン」が可能な状態だと、簡単に制御を奪われてしまいます。そこでUbuntu Coreでは「コンソールログインは原則不可」にしています。
しかしながらシステムにログインできないというのはそれはそれで不便なのでSSHでのログインは許可しています。とはいえパスワードログインを許可してしまうと、脆弱なパスワードを流用される可能性があります。「 より安全なほうへ」倒すために公開鍵認証を強制する形となりました。初回セットアップ時にSSHの公開鍵を簡単に登録できるようにするために、Ubuntu Oneアカウントを利用しているというわけです[2] 。
ちなみにこれらの挙動は「Ubuntu Coreベースの自前のイメージ」を作ることで回避可能ですし、そのためのツール・手順も用意されています。実際にUbuntu Coreベースのデバイスを作る場合、デプロイのたびにUbuntu Oneアカウントを入力するのは不便です。台数が増えてくるとヘッドレスインストールもほしくなってくるでしょう。そもそもインターネット接続がない環境でデプロイしたいかもしれません。ベンダー独自のストアを設定したい場合もあるはずです。このあたりは最終的に、デプロイそのものの自動化や、デバイスに合わせてベンダーごとがイメージを再作成するような形で対応していくことになります。あくまで「Ubuntuが提供するUbuntu Coreベースの標準システム」において、よりセキュアにできるというデモも兼ねてUbuntu Oneアカウントが必要だ、というだけです[3] 。
話を元に戻すと、現在のUbuntu Coreは初回インストール時に、SSH公開鍵取得のためのインターネット接続とセットアップ操作のためのディスプレイとキーボードが必要になります。先ほど作成したSDカードをRaspberry Piに装着し、起動してください。
図4 初回起動時はそれなりに時間がかかる
図5 準備ができたらEnterキーを押す
図6 初回起動はUbuntu Coreのインストール開始メッセージが表示される
図7 ネットワーク設定
図8 Ubuntu Oneアカウントのメールアドレスを入力する
ちなみにUbuntu Core 18時点ではインストール時にキーボードレイアウトを指定する方法が存在しません。英語キーボードでの入力となりますので、特に「@」の入力の際には注意してください。日本語キーボードのラベルだと「Shift+2」が「@」となります。
図9 インストールが完了
インストールが完了するとアクセス用のIPアドレスとSSHコマンドが表示されますので、デバイスに到達可能な端末からSSH接続してください。アカウント名もUbuntu Oneのそれに合わせて自動的に作られます。
ちなみにインストール直後はシステムの自動アップデートが行われ、すぐに再起動します。何をするにしてもしばらく待ったほうがいいでしょう。
図10 インストール後はディスプレイには接続案内のみが表示される
インストール後はディスプレイには接続案内しか表示されませんし、キーボード入力しても何も反応しません。よってSDカードを差し替えられたりしない限りは安全というわけです。もちろん「完全に安全」というわけではなく、単に誰でもすぐにログインを試せる状態ではないという程度の安全さです。
Ubuntu Coreの基本操作方法
ログインすると見た目上は普通のUbuntuです。
Welcome to Ubuntu Core 18 (GNU/Linux 5.3.0-1030-raspi2 armv7l)
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
* Ubuntu Core: https://www.ubuntu.com/core
* Community: https://forum.snapcraft.io
* Snaps: https://snapcraft.io
This Ubuntu Core 18 machine is a tiny, transactional edition of Ubuntu,
designed for appliances, firmware and fixed-function VMs.
If all the software you care about is available as snaps, you are in
the right place. If not, you will be more comfortable with classic
deb-based Ubuntu Server or Desktop, where you can mix snaps with
traditional debs. It's a brave new world here in Ubuntu Core!
Please see 'snap --help' for app installation and updates.
cosmos-door@localhost:~$
試しにaptコマンドやdpkgコマンドを使ってみましょう。
$ apt
Ubuntu Core does not use apt-get, see 'snap --help'!
$ dpkg
-bash: dpkg: command not found
aptコマンドを使おうとするとsnapを使うように指示されますし、dpkgコマンドに至っては、インストールすらされていません。
リソースの使用量を見てみましょう。今回はどこのご家庭にも死蔵されているであろうRaspberry Pi 2に32bit版のUbuntu Coreをインストールしてみました。
$ uname -a
Linux localhost 5.3.0-1036-raspi2 #38-Ubuntu SMP Thu Oct 15 14:42:05 UTC 2020 armv7l armv7l armv7l GNU/Linux
メモリの使用量は90MB程度です。ほとんど使っていないようですね。
$ free -h
total used free shared buff/cache available
Mem: 852M 90M 579M 8.9M 183M 739M
Swap: 0B 0B 0B
ルートファイルシステムはというと、ループバックデバイスになっているようです。
$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/loop0 46M 46M 0 100% /
Ubuntu Coreはベース部分を読み込み専用でマウントし、変更が必要な部分は別パーティションを用意し、個別にマウントする形を取っています。具体的には「writable」という名前の付いたパーティションが、変更可能なデータを保存するパーティションです。
$ df -h /writable/
Filesystem Size Used Avail Use% Mounted on
/dev/mmcblk0p2 7.1G 538M 6.2G 8% /writable
このため普通のLinuxっぽく/etc
以下の設定ファイルを書き換えても、再起動後には元に戻ってしまう可能性があります。しかしながら、最低限必要なものはきちんとwritableに残るようになっています。たとえばタイムゾーンの変更やホスト名の変更は、設定ファイルがwritableパーティションへのシンボリックリンクとなっているため、普通にtimedatectlやhostnamectlを利用できます。
$ sudo timedatectl set-timezone Asia/Tokyo
$ timedatectl
Local time: Sat 2020-12-12 22:07:19 JST
Universal time: Sat 2020-12-12 13:07:19 UTC
RTC time: n/a
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
systemd-timesyncd.service active: no
RTC in local TZ: no
$ sudo hostnamectl set-hostname raspi
$ hostname
raspi
Snappyの頃は「classicモード」と呼ばれる、普通のLinuxのようにルートファルシステムを変更できるモードが存在しました。現在でもclassicパッケージをインストールすれば、同等のことを実現可能であるのですが、これは将来的に削除される見込みです。どうしてもUbuntu Core上に普通のLinuxシステムがほしい場合は、LXDをインストールするのが一番簡単でしょう。
ちなみに起動時間はこんな感じです。Snappyの頃は起動にかなり時間がかかっていたのですが、最近は30秒を切るぐらいにまでなってきました。
$ systemd-analyze
Startup finished in 9.453s (kernel) + 15.605s (userspace) = 25.058s
graphical.target reached after 15.532s in userspace
Nextcloudパッケージのインストール
今回はsnapパッケージを使用する例として、NextcloudをインストールしてRaspberr PiをNASっぽく使えるようにしてみましょう。
Raspberry Piの場合は、次のようなsnapパッケージが最初からインストールされています。
$ snap list
Name Version Rev Tracking Publisher Notes
core18 20200929 1937 latest/stable canonical✓ base
pi 18-1 73 18-pi/stable canonical✓ gadget
pi-kernel 5.3.0-1036.38 219 18-pi/stable canonical✓ kernel
snapd 2.48.1 10495 latest/stable canonical✓ snapd
ここにnextcloudパッケージをインストールします。snap版のnextcloudパッケージについては、第476回の「Nextcloudに学ぶsnapパッケージ入門 」を参照してください。
snapパッケージのインストール方法は「findでパッケージを検索」し、「 infoでパッケージの情報・バージョンを確認」して「installでインストール」する流れとなります。
$ snap find nextcloud
Name Version Publisher Notes Summary
nextcloud 20.0.3snap1 nextcloud✓ - Nextcloud Server - A safe home for all your data
spreedme 0.29.5snap1 nextcloud✓ - Spreed.ME audio/video calls and conferences feature for the Nextcloud Snap
qownnotes 20.12.4 pbek - Plain-text file markdown note taking with Nextcloud / ownCloud integration
(以下略)
「✓」がついてるパッケージはストア側で「公式認定」した公開者のパッケージです。それ以外にも開発者は自由にパッケージをアップロード可能です。
とりあえず「nextcloud」という名前で正しいようです。
$ snap info nextcloud
name: nextcloud
summary: Nextcloud Server - A safe home for all your data
(略)
description: |
(略)
commands:
- nextcloud.disable-https
(略)
services:
nextcloud.apache: simple, enabled, active
(略)
channels:
latest/stable: 20.0.3snap1 2020-12-10 (24942) 258MB -
latest/candidate: ↑
latest/beta: ↑
latest/edge: master-2020-12-12 2020-12-12 (24995) 272MB -
20/stable: 20.0.3snap1 2020-12-10 (24942) 258MB -
20/candidate: ↑
20/beta: ↑
20/edge: 20-2020-12-12 2020-12-12 (24994) 258MB -
infoは大量の情報を表示するので、重要なところだけ抜粋しました。「 description」には概要だけでなくインストール時に必要な作業等が記述されていることもあるので、きちんと読んでおきましょう。「 channels」はどのリリースをインストールするかの指定となります。常に最新のリリースに自動更新されて良いのであれば、特に気にする必要はありません。バージョン20のみを使いたい(バージョン21が出ても自動アップデートしてほしくない)場合は、インストール時に「--channel=20/stable
」のように指定します。
今回は何も指定せずにインストールしてみましょう。
$ snap install nextcloud
nextcloud 20.0.3snap1 from Nextcloud✓ installed
snapによるシステムの変更履歴は、changesコマンドで確認できます。
$ snap changes
ID Status Spawn Ready Summary
1 Done today at 21:02 JST today at 21:03 JST Initialize system state
2 Done today at 21:04 JST today at 21:05 JST Initialize device
3 Done today at 21:05 JST today at 21:16 JST Auto-refresh snaps "snapd", "pi-kernel", "core18"
4 Done today at 21:39 JST today at 21:44 JST Install "nextcloud" snap
さて、nextcloudパッケージは無事にインストールされたので、しばらくするとHTTPサーバーが立ち上がります。ウェブブラウザーでUbuntu CoreをインストールしたデバイスのIPアドレスにアクセスしてください。
図11 おなじみの管理者アカウント作成画面
アカウント情報を入力したら、「 セットアップを完了します」を押してしばらく待ってください。Raspberry Piだと環境によっては「かなり」待つ必要があるかもしれません。Raspberry Pi 2の場合、「 推奨アプリのインストール」のチェックを外したとしても30分ぐらい待つ必要がありました。正直な話、Raspberry Pi 2では最近のNextcloudを動かすには若干力不足な感じはしています。
図12 おなじみのファイル一覧
あとはただのNextcloudなので自由に使ってください。ただしRaspberry Piの場合は、このままだとメインストレージがSDカードになってしまいます。できればより大きなストレージを外付けしたいところですよね。その方法も説明しておきましょう。
まずUbuntu Coreにおいて外部ストレージをマウントする方法です。もちろんmountコマンドを使って手動でマウントできますが、サービスとしては手動マウントは避けたいところです。古式ゆかしいUnixユーザーなら/etc/fstabを編集しようとするかもしれません。しかしながら、Ubuntu Coreのfstabには次のようなコメントが存在します。
# Auto-generated by /init
# DO NOT EDIT THIS FILE BY HAND - YOUR CHANGES WILL BE OVERWRITTEN
どうやらこのファイルを編集するのはまずそうです。では、どうやってシステム起動時に外部ストレージをマウントするのが良いのでしょうか。そこで出てくるのが、みんな大好きsystemdです。システムがバックグラウンドで自動的にやるような処理はだいたいsystemdで実現可能です。もちろんストレージのマウントも例外ではありません。
まずはmount unitファイルを作成しましょう。Ubuntu Coreの「/etc/systemd/
」は書き込み可能領域の「/writable/system-data/etc/systemd/
」をbind mountしています。よってどちらを編集してもかまいません。
$ cat <<'EOF' | sudo tee /writable/system-data/etc/systemd/system/media-data.mount
[Unit]
Description=External Storage for Nextcloud
[Mount]
What=/dev/disk/by-label/EXT
Where=/media/data
Type=ext4
[Install]
WantedBy=multi-user.target
EOF
ポイントは次のとおりです。
Whatでディスクラベルを使ってストレージを指定
Whereでマウントポイントを指定
Typeでファイルシステムを指定
Whatについては他にもUUIDなどを利用可能ですし、純粋にデバイスファイルを決め打ちすることも可能です。このあたりは用途に合わせて変更すると良いでしょう。
気をつけなければいけないのはマウントポイントとunitファイルのファイル名の関係です。systemdではマウントポイントを「/foo/bar」のような名前にする場合、unitファイル名は「foo-bar.mount」とする必要があります。これを守らないと、「 Invalid argument」エラーとなるので注意してください。
今回はシンプルに依存関係なども考えない設定にしましたが、他のサービスが起動するより前にマウントされていなければならない、などより細かい設定を考える必要があるかもしれません。たとえば第557回の「systemdのユニットの関係を読む 」にはunit間の関係を考える上で基本的な情報が載っていますので、そちらも参照すると良いでしょう。
あとは設定ファイルをリロードして、mount unitを起動し、無事にマウントされるようであれば、mount unitを次回起動時にも自動的に立ち上がるようにしておきます。
$ sudo systemctl daemon-reload
$ sudo systemctl start media-data.mount
$ sudo systemctl enable media-data.mount
さらにnextcloudパッケージから「/media/data」が見えるようにしておきます。一般的なsnapパッケージは、アクセスできる領域が限定されています。たとえば特定の設定が行われないと、ホームディレクトリにもアクセスできません。そこで利用するのが「interface」という仕組みです。
removable-mediaインターフェースは、指定したsnapパッケージから「/mnt」と「/media」以下にアクセスできる権限を付与します。
$ sudo snap connect nextcloud:removable-media
これでnextcloudから/media/data以下が見えるようになりました。あとはnextcloudの保存ディレクトリを/media/data以下に変更するだけです。実はnextcloudの管理者アカウントを作成したあとだと、少しだけ手順が複雑になります。詳しいことはsnap版nextcloudパッケージのWikiページ の後半を参照してください。もしNextcloud上にまだ何も保存していないなら、一度「snap remove nextcloud」した上で、Wiki上の前半の手順を実施しても良いでしょう。
Ubuntu Coreを紹介する都合上、ここまで何度もIoT、IoTと書いてはみたものの、結局IoTとは関係ない記事になってしまいました。