Ubuntu Weekly Recipe

第650回Ubuntu Coreのインストールを自動化する

第649回ではIoTデバイス用のプラットフォームとして利用されているUbuntu Coreの独自イメージの作り方を紹介しました。独自イメージを作れるようになると、各種アサーションを設定できるようになります。そこで今回はsystem-user assertionを利用して、Ubuntu Coreのインストールを自動化しましょう。

任意の管理者を追加できる「system-user assertion」

第649回でも解説しましたが、あらためてUbuntu Coreにおいてカスタムイメージを作成するメリットを紹介しておきましょう。

  • 任意のsnapパッケージがインストールされたイメージを構築できる
  • 初回セットアップをスキップできる
  • コンソールから直接ログイン可能に変更できる
  • 任意のカーネル・ブートローダーを利用できる

今回活用するのは二番目のメリットです。

通常配布されているUbuntu Coreはconsole-confによって初回セットアップ(Ubuntu SSOを利用したアカウントの作成)を必要としています。セットアップ済みのデバイスをmanagedと呼び、未セットアップなデバイスを「unmanaged」と呼びます。しかしながらインストールのたびにHDMIディスプレイとキーボードをつないで操作するのはいろいろと面倒です。そこで用意されているのが「設定済みのファイルをUSBスティックに保存し、それを接続して起動すれば自動セットアップしてくれる」モードです。これを実現するための設定ファイルをsystem-user assertionと呼びます。

system-user assertionはunmanagedなデバイスにのみ適用可能です。またその設定ファイル(アサーション)は、Coreイメージの作成者の鍵で署名されている必要があります。普通のUbuntu CoreはCanonicalの鍵で署名されているイメージのため、アサーションを作成できません。そこで自分の鍵で署名したカスタムイメージが必要になるのです。

第649回ですでにGPG鍵を~/.snap/gnupg/以下に作成済みであるとします。次のコマンドで鍵IDが表示されることを確認しておいてください。

$ snapcraft list-keys
    Name     SHA3-384 fingerprint
*   default  <鍵ID>

また、Snap Store上の開発者向けdashboardから「account-id」を取得しておいてください。

system-user assertionファイルの作成

実際に初回セットアップで何をしているかというと、Ubuntu SSO経由でアカウント情報とSSHの公開鍵を取得し、その内容からローカルアカウントを作成しているだけです。つまりこの情報を別の手段で提供すれば、インストールを自動化できます。この情報そのものがsystem-user assertionとなります。

Ubuntu Coreではデバイスがunmanagedなら、つまり初回セットアップも実施されず、過去にsystem-user assertionでアカウントも作られていなければ、起動時にUSBスティック上のルートディレクトリにauto-import.assertという名前のファイルが存在するかを確認します。もし存在すればそのファイルを用いてセットアップを行う仕組みになっているのです。

auto-import.assertは次の二種類の情報をまとめた、署名済みのYAMLファイルです。

  • そのアサーションに署名を行ったSnap Store上のユーザー情報
  • system-userとして作成するアカウント情報

つまり単に作成したいアカウントを記述するだけでなく、そのデバイスイメージに対して(modelに対して)アカウントを作成する権限があるユーザーによって署名したかどうかを記録する必要があるのです。この点が、model assertionを作ったときと異なります[1]⁠。

これらをまとめて正しいYAMLファイルを作るのは少し面倒なため、そのものずばりの「make-system-user」というコマンドが用意されています。まずはそのコマンドをインストールしましょう。

$ sudo snap install make-system-user --classic

あとは第649回で作成したmodel assertionがあるディレクトリで次のコマンドを実行します。

$ make-system-user \
  -b <Snap Storeのaccount-id> \
  -m pc \
  -u <作成したいユーザー名> \
  -e <Ubuntu SSOアカウントのメールアドレス> \
  -k default \
  -s '<~/.ssh/id_rsa.pubの中身>'

Done. You may copy auto-import.assert to a USB stick and insert
it into an unmanaged Core system, after which you can log in
using the username and password you provided.

account-idはカスタムイメージ作成時と同じSnap Storeから取得した文字列です。model assertionで使ったbrand-idと同じである必要があります。-m pcはmodel assertionのモデル名です。

「作成したいユーザー名」はUbuntu Coreシステム上に作成する際のユーザー名となります。⁠Ubuntu SSOアカウントのメールアドレス」はそのユーザーに紐づくメールアドレスです。Ubuntu SSOのアカウントと同じである必要性が今ひとつわかりませんが、今回はそのように設定しています。独自のBrand SSOを利用する場合はそのアカウントに紐付いたメールアドレスを使うことになるはずです。

-k defaultsnapcraft list-keysで表示される鍵名を指定します。

最後の-s '<~/.ssh/id_rsa.pubの中身>'では登録する公開鍵をリストアップしています。複数の鍵を登録する場合は-s '鍵1' '鍵2'のように空白区切りで連結してください。またシングルクオートは必須です。シングルクオートの中にssh-rsa 鍵ID コメントのような文字列を記述します。

SSH公開鍵ではなくパスワード認証を行いたいなら、-p 生のパスワードのように指定します。

うまくいけばauto-import.assertが作られます。GPGで署名されたYAMLファイルなので、期待通りの値が入っているかは確認したほうが良いでしょう。特にSSHの公開鍵は、指定方法を間違えると正しいフィールドにならないので注意が必要です。

USBストレージ付きの仮想マシンの作成

このauto-import.assertをUSBストレージのルートディレクトリに配置し、デバイスに接続し、起動すれば自動設定が行われます。

KVM版の場合は適当なディレクトリを作って、そこを仮想FATファイルシステムなUSBストレージとして見せるのが良いでしょう。具体的には次の手順で実施します。

$ mkdir usb
$ mv auto-import.assert usb/

$ kvm -smp 2 -m 1500 -netdev user,id=mynet0,hostfwd=tcp::8022-:22 \
  -device virtio-net-pci,netdev=mynet0 -nographic \
  -drive file=pc/pc.img,format=raw \
  -drive file=fat:rw:usb,id=stick,if=none \
  -device nec-usb-xhci,id=xhci \
  -device usb-storage,bus=xhci.0,drive=stick

第649回のkvmコマンドとの違いは、末尾に追加した3行です。⁠usb」ディレクトリをFATなドライブとして見せ、それをSATAではなくUSB接続として見せるためのオプションとなります。

カスタムイメージ作成時にconsole-confを無効化していない場合は、起動したあとPress enter to configure.と表示されます。しかしながらバックグラウンドでセットアップが行われているので、しばらく放置しましょう。うまく設定できていれば、初回設定画面に移行しなくても、SSHでログインできるようになっているはずです。

KVMで自動セットアップが動くイメージとアサーションファイルの作成を確立したら、あとはRaspberry Pi向けに同じ対応を行うだけです。これでHDMIディスプレイやUSBキーボードがなくてもUbuntu Coreをインストールできるようになりました。

このsystem-user assertionとカスタムイメージ、さらにカスタムイメージ作成時に指定できるインストール済みsnapパッケージやcloud-configを組み合わせれば、特定の環境向けのカスタムイメージの大半は作成できるはずです。

おすすめ記事

記事・ニュース一覧