🐧

Linux 使いになりたい人のための Vagrant と VirtualBox の設定(Ubuntu 22.04 編)

2024/06/30に公開

はじめに

Vagrant は、HashiCorp が開発している OSS(オープンソースソフトウェア)で、これを使うと仮想マシンの作成および管理を簡単にすることができます。

本記事では、Ubuntu 22.04 に Vagrant をインストールして使う方法について説明します。仮想マシンソフトウェアとしては VirtualBox を使用します。

Vagrant と VirtualBox をインストールするだけなら簡単にできます。そのため、筆者は Ubuntu 22.04 の apt パッケージで Vagrant と VirtualBox をインストールすれば、すぐに使えるだろうと思っていました。ところが、手元にあった Ubuntu 22.04 に VirtualBox 7.0 をインストール済みのマシンで、vagrant パッケージを追加インストールして使おうとしたところ、エラーが発生してしまい、動作しませんでした。ということで、同じように困っている人がいると思うので記事にすることにしました。

この問題を解決するには、次の2つの対応が必要でした。

  1. VirtualBox 7.0 に対応している Vagrant を使うこと
  2. Secure Boot への対応

これらのうち、2. の Secure Boot については、これを無効にして使えば、エラーは起こらなくなるのですが、セキュリティ的に安全性が低くなります。そのため、Secure Boot を有効にしたまま、対応することにします。

ここでは、Secure Boot を有効にしたまま、Vagrant と VirtualBox が使えるように Ubuntu 22.04 の設定をする方法について説明します。Vagrant と VirtualBox については、記事執筆時点で最新のものを使用します。

Vagrant とは

Vagrant は、HashiCorp が開発している OSS(オープンソースソフトウェア)で、これを使うと仮想マシンの作成および管理を簡単にすることができます。Vagrant を使うことで、開発環境の構築を自動化することができます。その結果、プロジェクトに参加する開発者が各自のパソコンに同じ環境を簡単に用意することができるようになります。このように、同じ開発環境での作業を前提とするプロジェクトでは、開発プロセスを円滑に進めることができるようになります。

Vagrant の主な特徴は次のとおりです。

  1. 仮想環境のプロビジョニング
  2. 高いポータビリティ
  3. 仮想環境の高い再現性
  4. 構成管理ツールのサポート
  5. 仮想環境用ネットワークの構成をサポート

Vagrant を使用すると仮想環境のプロビジョニングが簡単にできます。プロビジョニングとは仮想マシンの初期設定や設定管理をすることです。利用可能な仮想環境としては、Docker、VirtualBox、VMware などがあります。

Vagrant は高いポータビリティがあります。これは、Vagrantfile と呼ばれる設定ファイルを使用して仮想環境を定義するため、異なる開発者やマシン間で簡単に環境構築に必要な情報を共有できます。

Vagrant を使うと、仮想環境の高い再現性も手に入ります。同じ Vagrantfile を使用することで、環境構築に必要な情報を共有することができ、それを使って各自が同じ環境を手元に構築することができます。プロジェクトに参加する開発者全員が同じ環境で作業できるため、「自分の環境では動いているのに、他の環境では動かない」といった問題を回避できます。

ここで、Vagrant でのプロビジョニングにあたっては、構成管理ツールである AnsibleChefPuppet などが利用可能です。これらを使って、仮想マシンの設定を自動化できます。

また、Vagrant では仮想環境用のネットワークを構成する機能もあるため、仮想マシンのネットワーク設定を簡単に構成でき、ポートフォワーディングやプライベートネットワークなどの設定が可能です。

VirtualBox と Vagrant のインストール

それでは、ここで使用する VirtualBox と Vagrant をインストールしましょう。

VirtualBox のインストール

Linux での VirtualBox のインストールは Linux_Downloads – Oracle VM VirtualBox を参考にして行います。

最初に apt-get コマンドがパッケージをダウンロードするときのリポジトリーの情報を登録するために、/etc/apt/sources.list.d/virtualbox.list ファイルを作成します。スクリプトにしておいて、実行するのが確実でしょう。

install_apt_source_vbox.sh
GPG=oracle-virtualbox-2016.gpg
URL=https://download.virtualbox.org/virtualbox/debian
TARGET=$(lsb_release -cs)
cat << EOS | sudo tee /etc/apt/sources.list.d/virtualbox.list
deb [arch=amd64 signed-by=/usr/share/keyrings/${GPG}] ${URL} ${TARGET} main
EOS

これを実行します。内部で sudo コマンドを実行しているので、実行時にアカウントのパスワードが要求されます。

sh ./install_apt_source_vbox.sh

次に、パッケージをダウンロードするときの検証に使う Oracle の公開鍵を登録します。正しい公開鍵を登録する必要があるので、きちんとチェックすることにします。

ここで、参考にした Oracle のダウンロードページに記載されている oracle_vbox_2016.asc のフィンガープリントの値は次のとおりです。この値が更新されている場合は、この後に紹介するスクリプトは、その値を使うように修正してください。

B9F8 D658 297A F3EF C18D  5CDF A2F6 83C5 2980 AECF
Oracle Corporation (VirtualBox archive signing key) <info@virtualbox.org>

目視チェックは大変なので、check_fingerprint_vbox.sh.sh スクリプトを用意して確認します。

check_fingerprint_vbox.sh.sh
wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc
x=$(LANG=C gpg --show-keys --with-fingerprint --keyid-format=short oracle_vbox_2016.asc | grep -e "Key" | awk -F '=' '{print $2}')
y=$(LANG=C gpg --show-keys --with-fingerprint --keyid-format=short oracle_vbox_2016.asc | grep -e "uid" | awk -F 'uid' '{print $2}')
echo $x > fingerprint_download.txt
echo $y >> fingerprint_download.txt

# <https://www.virtualbox.org/wiki/Linux_Downloads> に記載されているものを使用。
# ただし、`gpg` コマンドの出力に合わせて、`C18D  5CDF` は `C18D 5CDF` 修正。
cat << EOS > fingerprint.txt
B9F8 D658 297A F3EF C18D 5CDF A2F6 83C5 2980 AECF
Oracle Corporation (VirtualBox archive signing key) <info@virtualbox.org>
EOS

diff fingerprint.txt fingerprint_download.txt
if [ $? -ne 0 ]; then
    echo "error"
fi

参考にする Oracle のダウンロードページ https://www.virtualbox.org/wiki/Linux_Downloads に記載されているものを使用しますが、gpg コマンドの出力に合わせて、C18D 5CDFC18D 5CDF 修正してあります。

スクリプトを用意したら実行します。

sh check_fingerprint_vbox.sh.sh

フィンガープリントに差がない場合は、次のようになります。

$ sh check_fingerprint_vbox.sh.sh
  ← 何も表示されない

ちなみに、gpg コマンドの出力に合わせた修正をしなかった場合は、次のように最後に error という出力が出ます。とはいえ、上下に比較しやすく文字列が並ぶので、正しいものかどうかを確認するのは容易でしょう。

$ sh check_fingerprint_vbox.sh.sh
1c1
< B9F8 D658 297A F3EF C18D  5CDF A2F6 83C5 2980 AECF
---
> B9F8 D658 297A F3EF C18D 5CDF A2F6 83C5 2980 AECF
error

Oracle の公開鍵のフィンガープリントについて正しいことが確認できたら、gpg コマンドでシステムへ登録します。ダウンロードしたファイルを使うなら下記のコマンドを実行します。

sudo gpg --yes --output /usr/share/keyrings/oracle-virtualbox-2016.gpg \
    --dearmor ./oracle_vbox_2016.asc

ダウンロードと登録を同時にするなら下記のコマンドを実行します。

wget -O- https://www.virtualbox.org/download/oracle_vbox_2016.asc \
| sudo gpg --yes --output /usr/share/keyrings/oracle-virtualbox-2016.gpg --dearmor

以上で apt-get コマンド用のリポジトリー登録が済んだので、apt-get コマンドを次のように実行して VirtualBox 7.0 をインストールします。

sudo apt-get update
sudo apt-get install -y virtualbox-7.0

vagrant のインストール

Ubuntu 22.04 の apt-get コマンドでインストールできる vagrant コマンドは VirtualBox 7.0 に対応していないので、最新版をインストールします。インストール方法は、次の URL で説明されています。

このページを参考にして、ここでは VirtualBox のときと同じ順番で作業することにします。

まず、/etc/apt/sources.list.d/hashicorp.list を作成するスクリプト install_apt_source_vagrant.sh を用意します。

install_apt_source_vagrant.sh
GPG=hashicorp-archive-keyring.gpg
URL=https://apt.releases.hashicorp.com
TARGET=$(lsb_release -cs)
cat << EOS | sudo tee /etc/apt/sources.list.d/hashicorp.list
deb [signed-by=/usr/share/keyrings/${GPG}] ${URL} ${TARGET} main
EOS

これを実行します。内部で sudo コマンドを実行しているので、実行時にアカウントのパスワードが要求されます。

sh ./install_apt_source_vagrant.sh

次に HashiCorp の公開鍵を登録します。公式のインストール方法の説明ページで紹介されているスクリプトでは、HashiCorp の公開鍵については値が提示されていないので、正しい物が配布されていると信じて使うことにします。

wget -O- https://apt.releases.hashicorp.com/gpg | \
    sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

リポジトリーの準備ができたら vagrant パッケージをインストールします。

sudo apt-get update
sudo apt-get -y install vagrant

Secure Boot 対応

次に VirtualBox 7 について、Secure Boot 対応します。この対策をしないと、failed: modprobe vboxdrv failed. Please use 'dmesg' to find out why といったエラーが表示されて vagrant コマンドを使った仮想マシンの作成ができません。

対応について、参考にした URL は Ask Ubuntu にある次のページです。

Machine Owner Key (MOK) 機能を利用するにあたっては、opensslmokutils といったコマンドを使います。

まずは、MOK 用のキーペアを作成します。スクリプトを用意して実行しましょう。

generate_mok_keys.sh
mkdir /root/module-signing
openssl req -new -x509 -newkey rsa:2048 \
    -keyout /root/module-signing/MOK.priv \
    -outform DER \
    -out /root/module-signing/MOK.der \
    -nodes -days 36500 -subj "/CN=n100.example.jp/"
chmod 600 /root/module-signing/MOK.priv

管理者権限が必要なので sudo コマンドを使って実行します。

sudo sh ./generate_mok_keys.sh

ここで、openssl コマンドの実行にあたり、Common Name (コモンネーム) の値に何を指定するか決めておく必要があります。通常はマシン名かマシンの FQDN を指定すれば良いです。Common Name は、/CN=n100.example.jp/ で指定していて、ここでは n100.example.jp としてあります。

次に mokutil コマンドで /root/module-signing/MOK.der をインポート。このとき、直後の再起動時の認証に使うパスワード入力があります。ここで入力したパスワードは再起動後に必要なので覚えておきます。このパスワードは次回の再起動時のときだけ必要な一時的に使用するものなので、複雑なものにする必要はありません。

$ sudo mokutil --import /root/module-signing/MOK.der
[sudo] user001 のパスワード: ← sudo コマンドを実行したユーザー(ここでは user001)のパスワードを入力
input password: ← MOK 用パスワードを入力。入力しても表示されません
input password again:  ← 直前に入力したパスワードを再入力。入力しても表示されません

次に、VirtualBox 関連のファイルを署名するスクリプト /root/module-signing/sign-vbox-modules.sh を用意しておきます。

/root/module-signing/sign-vbox-modules.sh
#!/usr/bin/env bash
SCRIPT_DIR=$(cd $(dirname $0); pwd)
cd ${SCRIPT_DIR}
for modfile in $(dirname $(modinfo -n vboxdrv))/*.ko; do
    echo "Signing $modfile"
    /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 \
        /root/module-signing/MOK.priv \
        /root/module-signing/MOK.der "$modfile"
done

スクリプトを用意したら、実行可能にしておきます。

sudo chmod 700 /root/module-signing/sign-vbox-modules.sh

以上の準備ができたら、パソコンを再起動します。

すると、MOK manager EFI utility が実行されてセキュアブートの画面になります。画面内で、「Enroll MOK」を選択します。それから、インポートしたキーの確認をし、パスワード入力をしたら「continue」を選択します。すると、マシンの起動処理が進みます。

Ubuntu が再起動したら、用意してあった署名用のスクリプトを実行します。なお、この署名作業は、カーネルアップデート時に毎回必要となります。

sudo bash /root/module-signing/sign-vbox-modules.sh

これで、vboxdrv などに署名がされたので、これらがロードできることを確認します。確認するには modprobe コマンドを使います。

sudo modprobe vboxdrv

問題がないようなら、Ubuntu を再起動します。これで、Vagrant から VirtualBox 7.0 が使えるようになりました。

Vagrant の使用

環境を用意したら、Vagrant を使ってみましょう。

Vagrant で仮想マシンを作成

作成する仮想マシンについては、Vagrant の box を使います。これは https://vagrantcloud.com/ で提供されていて https://vagrantcloud.com/search で検索することができます。

ここでは、generic/ubuntu2204 の box を使ってみます。

最初に Vagrantfile を作成するために、vagrant init コマンドを使います。vagrant 用のディレクトリー ${HOME}/vagrant を作成してから Vagrantfile を作成します。

mkdir -p ${HOME}/workspace/vagrant
cd ${HOME}/workspace/vagrant
vagrant init generic/ubuntu2204

これで、Vagrantfile が作成されます。内容については、コメントを省略すると、次のような Ruby のプログラムになっています。

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "generic/ubuntu2204"
end

ここでは vagrant init 時に指定した generic/ubuntu2204config.vm.box の値になっています。このことからわかるように、Vagrantfileconfig.vm.box には使用する box を指定します。

Vagrant の仮想マシンを起動と SSH 接続

初期設定の Vagrantfile の内容のままで良いので、仮想マシンを起動してみます。仮想マシンを起動するには vagrant up コマンドを使います。これで、コマンド実行時のカレントディレクトリーにある Vagrantfile を使って起動した仮想マシンが起動できます。

vagrant up --provider=virtualbox

起動した Ubuntu の仮想マシンには SSH 接続することができます。そのためには、vagrant ssh コマンドを使います。これで、コマンド実行時のカレントディレクトリーにある Vagrantfile を使って起動した仮想マシンに SSH 接続できます。

vagrant ssh

通常の ssh コマンドを使うこともできます。その場合は、ポート番号 2222、仮想マシンのアカウントは vagrant を指定します。

ssh -p 2222 vagrant@localhost

パスワード認証のプロンプトが表示されるので、初期パスワードの vagrant を入力します。すると、ログインできます。ログアウトするには exit コマンドを使います。

vagrant$ exit

パスワード認証ではなく、公開鍵認証を使いたい場合は ssh-id-copy コマンドを使って自分の公開鍵を登録します。

ssh-copy-id -i ~/.ssh/id_ed25519 -p 2222 vagrant@localhost

ここで、vagrant ssh コマンドが使っている公開鍵認証用の秘密鍵は、Vagrantfile のあるディレクトリーを ${VAGRANT_DIR} とすると、${VAGRANT_DIR}/.vagrant/machines/default/virtualbox/private_key にあります。この秘密鍵はパスフレーズがないので、これを使うと認証なしで ssh コマンドで仮想マシンへ接続できます。

次のようなスクリプトを用意しておくと、役に立つことがあるでしょう。

#!/bin/sh
VAGRANT_DIR=$(cd $(dirname $0)/..; pwd)
OPT_KEY=${VAGRANT_DIR}/.vagrant/machines/default/virtualbox/private_key
ssh -i ${OPT_KEY} -p 2222 vagrant@localhost $@

ちなみに、ssh コマンドは引数にリモートで実行するコマンドを指定できます。次の例では echo "hello vagrant" のコマンドを実行しています。

$ ssh -p 2222 vagrant@localhost echo "hello vagrant"
hello vagrant

また、ファイルコピーにあたっては scp コマンドが使えます。ポート番号は -P オプションで指定します。実行例は次のようになります。

scp -P 2222 -r ../script/ vagrant@localhost:

仮想マシンの停止と削除

仮想マシンを停止するには vagrant halt コマンドを使います。これで、コマンド実行時のカレントディレクトリーにある Vagrantfile を使って起動した仮想マシンが停止されます。

vagrant halt

仮想マシンの状態を確認するには vagrant global-status コマンドを使います。このコマンドを実行すると、仮想マシンの一覧表示ができます。実行例は次のようになります。

$ vagrant global-status
id       name    provider   state    directory                                                                                          
---------------------------------------------------
87c911d  default virtualbox poweroff (略)/vagrant 

仮想マシンを削除するには vagrant destroy コマンドを使います。これで、コマンド実行時のカレントディレクトリーにある Vagrantfile を使って起動した仮想マシンが削除されます。

vagrant destroy

削除する仮想マシンの id を指定して、それを削除することもできます。この id の値は、仮想マシンの一覧表示からわかります。

vagrant destroy 87c911d

Discussion