CentOS 8.1911 の vagrant box を作ってみる

CentOS 8.1911 がリリースされたが、Vagrant Cloud の公式 box ではまだリリースされていない(2020/02/01時点)。

もちろんもう少し待っていればそのうちリリースされるだろうけど、諸事情によりすぐ使いたかったので、box のカスタマイズ方法の勉強も兼ねて自分用の CentOS 8.1911 box を作ってみた。

## CentOS 8.1911 の カスタム box を作る

* カスタマイズ用ディレクトリを準備する。

```
$ mkdir centos8custom
$ cd centos8custom/
```

* CentOS 8 v1905.1 の公式 box を起動する。

```
$ vagrant init centos/8 --box-version 1905.1
$ vagrant up
```

* CentOS 8.1911 へアップデートする。

```
$ vagrant ssh
[vagrant@localhost ~]$ sudo -s
[root@localhost vagrant]# cat /etc/centos-release
CentOS Linux release 8.0.1905 (Core) 
[root@localhost vagrant]# 
[root@localhost vagrant]# dnf update
(...)
[root@localhost vagrant]# cat /etc/centos-release
CentOS Linux release 8.1.1911 (Core) 
[root@localhost vagrant]# 
[root@localhost vagrant]# exit
[vagrant@localhost ~]$ logout
Connection to 127.0.0.1 closed.
$ 
```

* CentOS 8.1911 の box を作成する。

```
$ vagrant package
==> default: Attempting graceful shutdown of VM...
==> default: Clearing any previously set forwarded ports...
==> default: Exporting VM...
==> default: Compressing package to: /Users/demo/proj/centos8custom/package.box
$ 
```

* 作成した box を登録する。

```
$ vagrant box add centos8.1911 package.box 
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'centos8.1911' (v0) for provider: 
    box: Unpacking necessary files from: file:///Users/demo/proj/centos8custom/package.box
==> box: Successfully added box 'centos8.1911' (v0) for 'virtualbox'!
$ vagrant box list
centos/8           (virtualbox, 1905.1)
centos8.1911       (virtualbox, 0)
$ 
```

これでできた。と思ったけど…

## カスタマイズした box で起動する

作ったカスタム box で起動してみるとなんかエラーが出る。

* テスト用ディレクトリを準備する。

```
$ cd ..
$ mkdir vagrant-test
$ cd vagrant-test/
```

* カスタム box で起動する。

```
$ vagrant init centos8.1911
(...)
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos8.1911'...
(...)
==> default: Mounting shared folders...
    default: /vagrant => /Users/demo/proj/vagrant-test
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=1000,gid=1000 vagrant /vagrant

The error output from the command was:

mount: /vagrant: unknown filesystem type 'vboxsf'.

$ 
```

```vboxsf``` がない、と言われる。```vboxsf``` を使うには vagrant guest additions　とやらが必要らしいのだけど、そもそも元々の 1905.1 のイメージでもそんなの入ってなかったよね? 

## エラー原因を調べてみる

元々の 1905.1 の起動メッセージをよく見てみると以下のように表示されていた。これは  ```/vagrant``` が ```rsync``` で ```mount``` されているということだ。

```
==> default: Rsyncing folder: /Users/demo/proj/centos8custom/ => /vagrant
```

```rsync``` では box の起動時にしかファイルの同期がされないが、その代わり特別なプラグイン等がなくても使える。公式の centos の box ではこれがデフォルトで、それは良いのだが、なぜカスタマイズした box ではこれがデフォルトにならないのだろう?

というわけで、box の中身を見てみることにした。

まず公式の centos8 のbox。実体は以下のディレクトリに存在している。

```
$ cd ~/.vagrant.d/boxes/centos-VAGRANTSLASH-8/1905.1/virtualbox/
$ ls
CentOS-8-Vagrant-8.0.1905-1.x86_64.vmdk	box.ovf					metadata.json
Vagrantfile				box_update_check
$
```

ここの ```Vagrantfile``` を見てみると、あったあった。これがデフォルトの元だ。

```:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.base_mac = "52540072fe6e"
  config.vm.synced_folder ".", "/vagrant", type: "rsync"
end
```


続いてカスタマイズした box の方を見てみる。

```
$ cd ~/.vagrant.d/boxes/centos8.1911/0/virtualbox/
$ ls
Vagrantfile		box-disk001.vmdk	box.ovf			metadata.json		vagrant_private_key
$
```

```Vagrantfile``` を覗いてみると中身が全然違っていて、確かに ```synced_folder``` の設定がどこにも書いてない。

```:Vagrantfile
Vagrant::Config.run do |config|
  # This Vagrantfile is auto-generated by `vagrant package` to contain
  # the MAC address of the box. Custom configuration should be placed in
  # the actual `Vagrantfile` in this box.
  config.vm.base_mac = "52540072FE6E"
end

# Load include vagrant file if it exists after the auto-generated
# so it can override any of the settings
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
load include_vagrantfile if File.exist?(include_vagrantfile)

Vagrant.configure("2") do |config|
  config.ssh.private_key_path = File.expand_path("../vagrant_private_key", __FILE__)
end
```

この ```Vagrantfile``` はどうすればカスタマイズできるんだろう。

いろいろ調べてみた結果

* このファイルは ```vagrant package``` で作られる
* ```vagrant package``` コマンドの ```--vagrantfile``` でオプションでカスタマイズできる

らしいということがわかった。

ということでこれでカスタムboxを再作成してみる。

## CentOS 8.1911 の カスタム box を作る(再)

* カスタマイズ用ディレクトリへ戻り、box を起動する。

```
$ cd centos8custom/
$ vagrant up
```

* box 起動時に```rsync```同期されたファイルを削除しておく。

```
$ vagrant ssh
[vagrant@localhost ~]$ rm -rf /vagrant/*
[vagrant@localhost ~]$ logout
Connection to 127.0.0.1 closed.
$ 
```

* 古いパッケージを削除する。

```
$ rm package.box 
```

* カスタマイズ用 ```Vagrantfile.custom``` を作成する。

```:Vagrantfile.custom
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos8.1911"
  config.vm.synced_folder ".", "/vagrant", type: "rsync"
end
```

* カスタマイズ box を作成する。

```
$ vagrant package --vagrantfile Vagrantfile.custom 
```

* 古い box を削除し、再作成した box で置き換える。

```
$ vagrant box remove centos8.1911
$ vagrant box add centos8.1911 package.box 
$ vagrant box list
centos/8            (virtualbox, 1905.1)
centos8.1911        (virtualbox, 0)
$ 
```

これで登録された box の中身を見てみる。

```
$ cd ~/.vagrant.d/boxes/centos8.1911/0/virtualbox/
$ ls
Vagrantfile		box.ovf			metadata.json
box-disk001.vmdk	include			vagrant_private_key
$ ls include/
_Vagrantfile
$ 
```
```:Vagrantfile 
Vagrant::Config.run do |config|
  # This Vagrantfile is auto-generated by `vagrant package` to contain
  # the MAC address of the box. Custom configuration should be placed in
  # the actual `Vagrantfile` in this box.
  config.vm.base_mac = "52540072FE6E"
end

# Load include vagrant file if it exists after the auto-generated
# so it can override any of the settings
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
load include_vagrantfile if File.exist?(include_vagrantfile)

Vagrant.configure("2") do |config|
  config.ssh.private_key_path = File.expand_path("../vagrant_private_key", __FILE__)
end
```

このファイルは前と変わっていない。けど include しているファイルがある。

```:include/_Vagrantfile 
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos8.1911"
  config.vm.synced_folder ".", "/vagrant", type: "rsync"
end
```

これで設定が有効になるに違いない。


## 再作成した カスタマイズ box で起動する

* テスト用ディレクトリへ移動する。

```
$ cd ../vagrant-test/
```

* 古い box の VM が稼働している場合は破棄する。

```
$ vagrant destroy
$ rm Vagrantfile
```

* 再作成した カスタム box で起動する。

```
$ vagrant init centos8.1911
(...)
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos8.1911'...
(...)
==> default: Rsyncing folder: /Users/demo/proj/vagrant-test/ => /vagrant
$ 
```

できた! これで公式の centos8 box と同じ動作になった。

box の中身に登録されている ```Vagrantfile``` の構成まで全く同一にはならかなったが、おそらく公式の centos8 の box はまた別の手順でパッケージを作成しているのだろう。