vagrantのboxを自作する

vagrantのboxを自作する

ローカル開発環境にvagrantを使うことが多々有りますが、web上で公開されているboxを使うのは多少怖いです。
何が入ってるかわからんし、どんな設定が仕込まれてるかもわからんし、etc...
ということで、自分が安心納得なboxを自作します。

# 概要
VirtualBoxの仮想マシンを作成し、必要な設定を入れ、box化します。
ただし、そんな情報は世の中にありふれているので、出来る限りCLIから実施することを念頭に進めます。
box作成の全体の流れは以下のWebサイトを参考にさせていただきました。
[CentOS 6.6 x86_64 minimalのVagrant boxを作る - 作業ノート](http://te2u.hatenablog.jp/entry/2015/05/11/012225)
[VagrantのBoxを新しく作成する方法（VirtualBox / CentOS 6.6 x86_64） - TASK NOTES](http://www.task-notes.com/entry/20150611/1433991600)

## 手元の環境
* MacOS X El Capitan
* VirtualBox 4.3.28
* vagrant 1.7.2

# 仮想マシンの作成
## ベースとなるISOを入手
今回はCentOS6.7のboxを作ります。
以下からisoを事前にダウンロードしておきます。
http://ftp.riken.jp/Linux/centos/6/isos/x86_64/CentOS-6.7-x86_64-minimal.iso

## 仮想マシン作成
仮想マシンを作ります。

```bash
$ VBoxManage createvm --name centos67-minimal --ostype RedHat_64 --register
Virtual machine 'centos67-minimal' is created and registered.
UUID: 57496b6c-14da-4dfd-9326-8a0c5010d6a6
Settings file: '/Users/user01/VirtualBox VMs/centos67-minimal/centos67-minimal.vbox'
```

出来上がりました。確認しましょう。

```bash
$ VBoxManage list vms
"centos67-minimal" {57496b6c-14da-4dfd-9326-8a0c5010d6a6}
```

## 仮想マシン編集
まだ仮想マシンのハコが用意されただけなので、メモリなどを設定していきます。
ここでは以下の設定を入れています。

* メモリ 512MB
* VRAM 12MB
* ハードウェアクロックをUTCにする
* ブートデバイスからフロッピーを削除し、DVD,Diskの順に変更

```bash
$ VBoxManage modifyvm centos67-minimal \
  --memory 512 \
  --vram 12 \
  --rtcuseutc on \
  --boot1 dvd \
  --boot2 disk \
  --boot3 none
```

## 仮想ディスク作成
つづいて、仮想ディスクを作成します。

```bash
$ VBoxManage createhd \
  --filename "/Users/user01/VirtualBox VMs/centos67-minimal/centos67-minimal" \
  --size 8192
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Disk image created. UUID: f1c1fdd3-9ffc-48b1-a9c6-d3acd892808c
```

作成されました。確認しましょう。

```bash
$ VBoxManage showhdinfo "/Users/user01/VirtualBox VMs/centos67-minimal/centos67-minimal.vdi"
UUID:           f1c1fdd3-9ffc-48b1-a9c6-d3acd892808c
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/user01/VirtualBox VMs/centos67-minimal/centos67-minimal.vdi
Storage format: VDI
Format variant: dynamic default
Capacity:       8192 MBytes
Size on disk:   2 MBytes
```

## ストレージコントローラーを追加
仮想マシンにストレージを挿せるよう、ストレージコントローラーを追加します。

```bash
$ VBoxManage storagectl centos67-minimal \
  --name IDE \
  --add ide

$ VBoxManage storagectl centos67-minimal \
  --name SATA \
  --add sata \
  --portcount 1
```

## 仮想ディスクをアタッチ
DVDドライブをIDEのセカンダリマスターに接続します。
先ほど作成した仮想ディスクを仮想ディスクをSATAのPort0に接続します。

```bash
$ VBoxManage storageattach centos67-minimal \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium emptydrive
$ VBoxManage storageattach centos67-minimal \
  --storagectl SATA \
  --port 0 \
  --type hdd \
  --medium "/Users/user01/VirtualBox VMs/centos67-minimal/centos67-minimal.vdi"
```

これで仮想マシンは作成、準備出来ました。

# OSインストール
## OSディスク(ISO)のアタッチ
OSインストールのために、先ほどダウンロードしたISOをマウントします。

```bash
$ VBoxManage storageattach centos67-minimal \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium "/Users/user01/Downloads/CentOS-6.7-x86_64-minimal.iso"
```

## 仮想マシン起動とOSインストール
仮想マシンを起動します。

```bash
$ VBoxManage startvm centos67-minimal
Waiting for VM "centos67-minimal" to power on...
VM "centos67-minimal" has been successfully started.
```

仮想マシンのGUIが立ち上がるので、OSのインストールを進めていきます。
ここでは以下のサイトを参考にインストールを進めます。
[VagrantのBoxを新しく作成する方法（VirtualBox / CentOS 6.6 x86_64） - TASK NOTES](http://www.task-notes.com/entry/20150611/1433991600)
rootのパスワードは```vagrant```を設定しましょう。
インストールが終われば再起動し、コンソールに```root```でログインします。

## NIC有効化
このままだと```eth0```が有効化されていないので、コンソールで以下を実行し```eth0```を有効化します。

```bash
# sed -i -e "s/ONBOOT=no/ONBOOT=yes/" /etc/sysconfig/network-scripts/ifcfg-eth0
# service network restart
```

仮想マシンのコンソール上での作業はここまでです。

# OS設定
## 作業用SSH PortForward設定
最初に、eth0に対してSSH作業用にポートフォワードの設定を入れてしまいます。作業の最後に削除するので一時的な設定です。

```bash
$ VBoxManage controlvm centos67-minimal natpf1 ssh,tcp,,2222,,22
```

これで手元のMacからSSHできるようになりました。

```bash
$ ssh -p 2222 root@localhost
The authenticity of host '[localhost]:2022 ([127.0.0.1]:2022)' can't be established.
RSA key fingerprint is SHA256:Pd0xPQqTMf4A/CL73e0HU+5/pbXoKdaH9jGxaQavJRM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:2022' (RSA) to the list of known hosts.
root@localhost's password:
Last login: Thu Apr 14 02:34:03 2016
[root@localhost ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
```

以降はこのSSHセッションで作業します。

## yumのアップデート
一旦この時点でyumの更新をします。

```bash
# yum update -y
```

## VirtualBox Guest Additionsインストール
Guest Additionsをインストールするために、必要なパッケージ類を事前にインストールします。

```bash
# yum install -y kernel-devel
# yum install -y kernel-headers
# yum install -y gcc
# yum install -y perl
```

ここで忘れずに再起動を行います。

```bash
# reboot
```

再起動を待っている間に、Guest Additionのメディアをマウントします。

```bash
$ VBoxManage storageattach centos67-minimal \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium "/Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso"
```

再起動が終わったら、もう一度仮想マシンにSSHし、Guest Additionをインストールします。

```bash
# mkdir /media/cdrom
# mount -r /dev/cdrom /media/cdrom
# sh /media/cdrom/VBoxLinuxAdditions.run
Verifying archive integrity... All good.
Uncompressing VirtualBox 4.3.28 Guest Additions for Linux............
VirtualBox Guest Additions installer
Removing installed version 4.3.28 of VirtualBox Guest Additions...
Copying additional installer modules ...
Installing additional modules ...
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
Building the main Guest Additions module                   [  OK  ]
Building the shared folder support module                  [  OK  ]
Building the OpenGL support module                         [失敗]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]
Installing the Window System drivers
Could not find the X.Org or XFree86 Window System, skipping.
# umount /media/cdrom
```

OpenGLやXwindow関連はvagrantのboxなのでエラーが出てても無視してOKです。

## vagrantユーザ作成
vagrantユーザを、パスワード```vagrant```で作成します。

```bash
# useradd -m vagrant
# echo 'vagrant' | passwd --stdin vagrant
```

## ssh公開鍵認証設定
作成したvagrantユーザを、vagrantのSSH鍵認証で入れるようにします。

```bash
# mkdir /home/vagrant/.ssh
# chmod 700 /home/vagrant/.ssh
# curl -k -L -o /home/vagrant/.ssh/authorized_keys 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub'
# chmod 600 /home/vagrant/.ssh/authorized_keys
# chown -R vagrant:vagrant /home/vagrant/.ssh
```

## sudo設定
vagrantユーザで```sudo```できるようにします。
本来はvisudoコマンドで編集すべきなのですが、今回はコマンドラインでできることを念頭においているため、sedで作業します。

```bash
# sed -i -e "s/Defaults    requiretty/#Defaults    requiretty/" /etc/sudoers
# sed -i -e "/NOPASSWD/a vagrant\tALL=(ALL)\tNOPASSWD: ALL" /etc/sudoers
```

## iptables無効化
開発環境なのでiptablesを止めてしまいます。

```bash
# service iptables stop
# service ip6tables stop
# chkconfig iptables off
# chkconfig ip6tables off
```

## selinux無効化
こちらも同様に開発環境なのでselinuxを無効化します。

```bash
# sed -i -e "s/SELINUX=enforcing/SELINUX=disabled/" /etc/sysconfig/selinux
```

## udevルールの削除
boxのOS起動時にネットワークデバイスでエラーが出るらしいので、udevルールを削除しておきます。

```bash
# ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
# rm -rf /dev/.udev/
# rm -f /lib/udev/rules.d/75-persistent-net-generator.rules
```

## box化準備
ここまでで最低限必要なOS設定が終わりました。
box化する前にゴミ掃除と仮想ディスクのゼロ埋めをしておきます。

```bash
# yum clean all
# dd if=/dev/zero of=/EMPTY bs=1M
# rm -f /EMPTY
```

作業が終わったら仮想マシンをシャットダウンします。

```bash
# shutdown -h now
```

### 作業用SSH PortForwardの削除
SSH作業用に入れたポートフォワードの設定を削除します。

```bash
$ VBoxManage controlvm centos67-minimal natpf1 delete ssh
```

### VirtualBox Guest Additionsメディアのアンマウント
こちらもbox化前にアンマウントしておきます。

```bash
$ VBoxManage storageattach centos67-minimal \
  --storagectl IDE \
  --port 1 \
  --device 0 \
  --type dvddrive \
  --medium emptydrive
```

# box作成
## box化
boxにパッケージングします。

```bash
$ vagrant package --base centos67-minimal
==> centos67-minimal: Exporting VM...
==> centos67-minimal: Compressing package to: /Users/user01/vagrant/box/package.box
$ ls -lah /Users/user01/vagrant/box/package.box
-rw-r--r--  1 user01  user01   405M  4 17 19:26 /Users/user01/vagrant/box/package.box
```

約400MBのboxが出来上がりました。

せっかくなのでboxの登録と起動確認まで行います。

```
$ vagrant box add --name CentOS67 package.box
==> box: Adding box 'CentOS67' (v0) for provider:
    box: Downloading: file:///Users/user01/vagrant/box/package.box
==> box: Successfully added box 'CentOS67' (v0) for 'virtualbox'!
$ vagrant box list
CentOS67 (virtualbox, 0)
$ ls -l ~/.vagrant.d/boxes/CentOS67/0/virtualbox/
total 876152
-rw-r--r--  1 user01  user01        505  4 17 19:31 Vagrantfile
-rw-------  1 user01  user01  448564736  4 17 19:31 box-disk1.vmdk
-rw-------  1 user01  user01      12612  4 17 19:31 box.ovf
-rw-r--r--  1 user01  user01         25  4 17 19:31 metadata.json
$ vagrant init CentOS67
$ vagrant up
$ vagrant ssh
[vagrant@localhost ~]$
```

無事```vagrant up```までできました。

## 仮想マシン削除
boxを作成し終わったので、box作成済みの仮想マシンを削除します。

```bash
$ VBoxManage unregistervm centos67-minimal --delete
```

# まとめ
OSインストールの部分以外は基本的にCLIで作業が出来ました。
これで安心してboxを作成・活用できますね！

## スクリプト化
一連の作業を一気通貫で実行してくれるスクリプトを作成しました。
https://gist.github.com/mochidamochiko/973895e2eca648339cb1126cd39dd409

## その他
コレを書いている最中に、box作成の便利ツールがあることを知りました… orz

* veewee [jedi4ever/veewee: Easing the building of vagrant boxes](https://github.com/jedi4ever/veewee)
* packer [Packer by HashiCorp](https://www.packer.io/)


# 参考資料類
[Creating a Base Box - Vagrant by HashiCorp](https://www.vagrantup.com/docs/boxes/base.html)
[Oracle VM VirtualBox® Manual Chapter 8. VBoxManage](https://www.virtualbox.org/manual/ch08.html)
[CentOS 6.6 x86_64 minimalのVagrant boxを作る - 作業ノート](http://te2u.hatenablog.jp/entry/2015/05/11/012225)
[VagrantのBoxを新しく作成する方法（VirtualBox / CentOS 6.6 x86_64） - TASK NOTES](http://www.task-notes.com/entry/20150611/1433991600)