Vagrantで自作boxをDropboxで共有しつつバージョニングもしたい

# はじめに

## 目的
タイトルの通り。
chef-solo使ってもいいけど~~結局自前で書く設定が多そうで面倒くさそうという偏見があり~~いじり倒したイメージを共有したい。
できるだけ手軽かつコンパクトに。
……という仕組みが欲しかったのですが、やってる人がいそうな割に情報がまとまっていなかったので記事書きました。

## 完成形
ある端末からboxを更新したときはvagrant packageコマンドでboxを作成する。
他の端末からはvagrant box updateコマンドを叩いて最新のboxに更新する。
boxを作成する端末は固定しない。

この例で作る構造はこんな感じ↓

```
vm(Dropbox内のディレクトリ)
├─centos65dev
│  │  centos65dev.box
│  │  centos65dev-win.json
│  │  Vagrantfile
│  └─.vagrant(共有しない)
└─centos65temp(途中で削除するので以下略)
```

## 注意
複数人が同時にboxを更新するケースなどは特に想定していません。
基本的にはDropboxでの管理なので、その辺はDropboxがうまくやってくれるでしょう。

# 準備
各端末にはDropboxとVagrantとVirtualBoxをインストールしておく。
動作確認した環境は以下。
OS : Windows 7/8.1
Dropbox : 3.0.3
Vagrant : 1.7.2
VirtualBox : 4.3.20
ローカルファイルのパスを記載するところがあるので、Dropboxのディレクトリはできるだけ統一しておく。
(MacとLinuxに対しては未検証だけど、パスだけ違うjsonファイルを作ればいいはず)

# box作成手順
## 1. 1台目の端末から仮想マシンを作成
基本的には普通に作ってしまって問題ない。
VagrantのコマンドをDropbox以下の何処かのディレクトリで実行する。
マシンごとに別のサブディレクトリに入れる構造にしておこう。
(例では作業ディレクトリをC:\Dropbox\vmとする)
この時点では同期を一時停止しておいていい。

最初に作るboxはバージョン情報が入らないので、一時的なものとして扱い、バージョン情報などを入れて新たに入れ直すのがよさそうである。
この例ではcentos6.5のboxを使用している。

```
$ mkdir centos65temp
$ cd centos65temp
$ vagrant box add centos65temp https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
$ vagrant init centos65temp
(必要に応じてここでVagrantfileを編集)
$ vagrant up
```

まずはSSHで接続するなどして、起動を確認する。

## 2. 現在の環境からboxを作成する
box作成時のときのために、MACアドレスがくっつかないようにしておく。
詳しくは[VMイメージ内でMACアドレスとインターフェース名(eth0とか)の関係が固定化されるのを防ぐ](http://qiita.com/kawaz/items/dc33294c907755e9ee44)を見るとよさそう。
仮想マシンで以下のコマンドを叩いておく。

```
# rm -f /etc/udev/rules.d/70-persistent-net.rules
# mkdir /etc/udev/rules.d/70-persistent-net.rules
```

準備ができたら、端末側でvagrant packageコマンドを叩く。
仮想マシンが起動中のときは、実行時に自動で仮想マシンがシャットダウンされる。

```
$ vagrant package --output centos65dev.box
```

カレントディレクトリに同名のファイルができるので、これを新たなディレクトリに移動する。カレントディレクトリもそちらに変更。
(この例ではvm\centos65dev)

## 3. バージョン情報のjsonを記述する

実はここでやっていることはほぼ[Vagrant自作Boxのバージョニング](http://tsunokawa.hatenablog.com/entry/2014/10/24/153151)からの引用である。
何が違うかというと、ここで指定しているurlというパラメータは[ローカルファイルも使える](https://docs.vagrantup.com/v2/boxes/format.html)という点である。
つまりboxファイルをDropboxに放り込めばそのファイルを参照するようにできるので、明示的なアップロードが不要ということだ。
多分これが一番早いと思います(フラグ)

centos65dev-win.jsonを以下の内容で作成する。

```
{
    "description": "CentOS6.5 x86_64 dev",
    "short_description": "CentOS6.5",
    "name": "centos6.5",
    "versions": [{
        "version": "0.0.1",
        "status": "active",
        "description_html": "<p>CentOS6.5 x86_64</p>",
        "description_markdown": "CentOS6.5 x86_64",
        "providers": [{
            "name": "virtualbox",
            "url": "file://C:/Dropbox/vm/centos65dev/centos65dev.box"
        }]
    }]
}
```

ローカルファイルのパスを指定するので、少なくともOSごとに別のjsonファイルを指定することになる。

## 4. jsonファイルからboxを追加して起動

先ほどはboxのurlを指定していたところに、今作ったjsonファイルを指定する。

```
$ vagrant box add centos65dev-win.json
```

box: Successfully added box 'centos65dev' (v0.0.1) for 'virtualbox'!
のようなメッセージが出れば無事追加完了である。確認してみよう。

```
$ vagrant box list
centos65dev  (virtualbox, 0.0.1)
centos65temp (virtualbox, 0)
```

あとは通常通り起動すればよい。

```
$ vagrant init centos65dev
(Vagrantfileを編集)
$ vagrant up
(起動確認)
```

起動確認したら一旦終了して、Dropboxの同期対象からカレントディレクトリ以下にできた.vagrantディレクトリを外しておこう。
外し忘れると[Dropboxで複数マシン間でVagrant開発環境を同期している時に、vagrant upで既存仮想マシンが利用されない問題](http://qiita.com/hashcc/items/438ad3cd81f16bc6d6fa)が発生する。
なお、同期対象から外したときに一度このディレクトリは消去されるので、仮想マシン起動中は行わないこと。

これで手順は終了。Dropboxの同期はこの時点で再開するといいだろう。
あとは他の端末からもjsonファイルを指定してvagrant box addコマンドを叩けばよい。

boxの更新時にjsonファイルのバージョンなどを書き換えると、他の端末からvagrant updateコマンドを叩くことでboxを更新できる。