Packer で Ubuntu 12.04 の Vagrant Box を作る

Ubuntu 公式の ISO ファイルを元に、ローカルの開発環境で使う Vagrant box の作成を試みました。

# 設定ファイルを用意する

以下のファイルを用意します。

```
.
|-- template.json
|-- http
|   `-- preseed.cfg 
`-- setup.sh
```

## template.json

Packer が使うテンプレートです。[VirtualBox Builder (from an ISO)](http://www.packer.io/docs/builders/virtualbox-iso.html) を参考に書きました。あとはこれに [Ansible (Local) Provisioner](http://www.packer.io/docs/provisioners/ansible-local.html) や [Chef-Solo Provisioner](http://www.packer.io/docs/provisioners/chef-solo.html) などの設定を足すと良いと思います。

```json
{
  "builders": [
    {
      "type": "virtualbox-iso",
      "guest_os_type": "Ubuntu_64",
      "iso_urls": [
        "http://ftp.jaist.ac.jp/pub/Linux/ubuntu-releases/12.04/ubuntu-12.04.4-server-amd64.iso",
        "http://releases.ubuntu.com/12.04/ubuntu-12.04.4-server-amd64.iso"
      ],
      "iso_checksum": "e83adb9af4ec0a039e6a5c6e145a34de",
      "iso_checksum_type": "md5",
      "ssh_username": "vagrant",
      "ssh_password": "vagrant",
      "shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
      "headless": true,
      "http_directory": "http",
      "boot_command": [
        "<esc><esc><enter><wait>",
        "/install/vmlinuz noapic ",
        "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
        "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
        "hostname={{ .Name }} ",
        "fb=false debconf/frontend=noninteractive ",
        "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
        "keyboard-configuration/variant=USA console-setup/ask_detect=false ",
        "initrd=/install/initrd.gz -- <enter>"
      ]
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "setup.sh"
    }
  ],
  "post-processors": [
    {
      "type": "vagrant",
      "output": "my-precise64.box"
    }
  ]
}
```

|項目|備考|
|:--|:--|
|iso_urls|[release.ubuntu.com](http://releases.ubuntu.com/) の他に [Official CD Mirrors for Ubuntu](https://launchpad.net/ubuntu/+cdmirrors) の URL を足しています|
|iso_checksum|http://releases.ubuntu.com/12.04/MD5SUMS の値です|
|ssh_username|後述する preseed.cfg で設定した値を書いています|
|ssh_password|同上|
|headless|試行錯誤するときは false にした方が、インストールの様子が分かるので便利です|
|http_directory|後述する preseed.cfg を置くディレクトリの場所です|
|boot_command|公式ドキュメントの [Boot Command](http://www.packer.io/docs/builders/virtualbox-iso.html#toc_3) に載っている例そのままです|

## http/preseed.cfg

パーティションやユーザアカウントなどの設定に使うファイルです。[Ubuntu Installation Guide](https://help.ubuntu.com/12.04/installation-guide/amd64/index.html) の [Using preseeding](https://help.ubuntu.com/12.04/installation-guide/amd64/preseed-using.html) から辿れる[サンプル](https://help.ubuntu.com/12.04/installation-guide/example-preseed.txt)を元にしました。インストーラが入力待ちで止まらないようにしたり vagrant という名前のユーザアカウントを作るようにしたりといった変更を加えています。ユーザ名とパスワードを vagrant にするのは、そういう[要求](http://docs.vagrantup.com/v2/boxes/base.html)があるからです。具体的な差分は次の通りです。

```diff
--- example-preseed.txt	2014-03-14 18:20:32.000000000 +0900
+++ preseed.cfg	2014-03-14 18:25:31.000000000 +0900
@@ -138,10 +138,11 @@
 d-i partman-md/device_remove_md boolean true
 # And the same goes for the confirmation to write the lvm partitions.
 d-i partman-lvm/confirm boolean true
+d-i partman-lvm/confirm_nooverwrite boolean true
 
 # For LVM partitioning, you can select how much of the volume group to use
 # for logical volumes.
-#d-i partman-auto-lvm/guided_size string max
+d-i partman-auto-lvm/guided_size string max
 #d-i partman-auto-lvm/guided_size string 10GB
 #d-i partman-auto-lvm/guided_size string 50%
 
@@ -274,18 +275,18 @@
 #d-i passwd/root-password-crypted password [MD5 hash]
 
 # To create a normal user account.
-#d-i passwd/user-fullname string Ubuntu User
-#d-i passwd/username string ubuntu
+d-i passwd/user-fullname string Vagrant
+d-i passwd/username string vagrant
 # Normal user's password, either in clear text
-#d-i passwd/user-password password insecure
-#d-i passwd/user-password-again password insecure
+d-i passwd/user-password password vagrant
+d-i passwd/user-password-again password vagrant
 # or encrypted using an MD5 hash.
 #d-i passwd/user-password-crypted password [MD5 hash]
 # Create the first user with the specified UID instead of the default.
 #d-i passwd/user-uid string 1010
 # The installer will warn about weak passwords. If you are sure you know
 # what you're doing and want to override it, uncomment this.
-#d-i user-setup/allow-password-weak boolean true
+d-i user-setup/allow-password-weak boolean true
 
 # The user account will be added to some standard initial groups. To
 # override that, use this.
@@ -325,23 +326,25 @@
 #d-i debian-installer/allow_unauthenticated boolean true
 
 ### Package selection
-tasksel tasksel/first multiselect ubuntu-desktop
+#tasksel tasksel/first multiselect ubuntu-desktop
 #tasksel tasksel/first multiselect lamp-server, print-server
 #tasksel tasksel/first multiselect kubuntu-desktop
+tasksel tasksel/first multiselect standard
 
 # Individual additional packages to install
-#d-i pkgsel/include string openssh-server build-essential
+d-i pkgsel/include string openssh-server
 # Whether to upgrade packages after debootstrap.
 # Allowed values: none, safe-upgrade, full-upgrade
-#d-i pkgsel/upgrade select none
+d-i pkgsel/upgrade select none
 
 # Language pack selection
 #d-i pkgsel/language-packs multiselect de, en, zh
+d-i pkgsel/install-language-support boolean false
 
 # Policy for applying updates. May be "none" (no automatic updates),
 # "unattended-upgrades" (install security updates automatically), or
 # "landscape" (manage system with Landscape).
-#d-i pkgsel/update-policy select none
+d-i pkgsel/update-policy select none
 
 # Some versions of the installer can report back on what software you have
 # installed, and what software you use. The default is not to report back,
```

## setup.sh

template.json の ``provisioners`` の項目で指定した初期設定用のスクリプトです。[Creating a Base Box](http://docs.vagrantup.com/v2/boxes/base.html) に従い、パスワードなしでログインや sudo できるようにしています。

```bash
#!/bin/sh

set -ex

# password-less login
mkdir ~/.ssh
chmod 0700 ~/.ssh
wget -qO- https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub > ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keys

# password-less sudo
echo 'vagrant' | sudo -S sh -c "echo 'vagrant ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vagrant"
echo 'vagrant' | sudo -S chmod 0440 /etc/sudoers.d/vagrant
```

# box ファイルを作る

簡単ですが時間はかかります。

```shell-session
$ packer build template.json
```

# box ファイルを使う

[vagrant-vbguest](https://github.com/dotless-de/vagrant-vbguest) をインストールしておくと Vagrant に VirtualBox Guest Additions の面倒をみてもらえます。

```shell-session
$ vagrant plugin install vagrant-vbguest
$ vagrant box add --name my-precise64 my-precise64.box
$ vagrant init my-precise64
$ vagrant up
$ vagrant ssh
```

# トラブルシューティング

公式ドキュメント以外では [packer 触っててハマった時は veewee 眺めると幸せになれる](http://mgi.hatenablog.com/entry/2013/12/14/102352)話が参考になりました。