Creating a Custom Vagrant Box from Scratch
Table of Contents
We begin by understanding what a “.box” file is. A Vagrant “.box” is simply a tarred gzip package containing, at minimum, the VM’s metafiles, disk image(s), and a metadata.json; which identifies the provider the box has been created for. Other optional supporting files, such as a custom Vagrantfile, can be packaged with the box if desired.
Sanity Check #
A quick sanity test. The instructions have been generalized and should work with most Hosts and Guests of a similar configuration. Only the below have been tested. So no guarantees explicit or implied.
Our Host #
This article assumes an OS X development environment. All software on the Host should be assumed the OS X version unless otherwise stated.
- Apple OS X Mountain Lion (10.7.5)
- VirtualBox 4.2.12
- VMware Fusion 5.0.4
- Vagrant 1.2.2
- Vagrant’s VMware Fusion provider 0.6.3 with a valid license.
Potential Guests #
All tested Guests are 64-bit distributions of Linux.
- CentOS 6.4
- Debian 7.0
- Scientific Linux 6.4
- Ubuntu 12.10 Desktop
- Ubuntu 12.10 Server
Create the Virtual Machine #
Start by launching the virtualization software and creating a VM which our Vagrant box will be based off of. The following configuration options are recommended when defining the VM:
VirtualBox #
Create a new VM in VirtualBox:
- Name: vagrant-<distro><arch> i.e. vagrant-centos64
- Type: Linux
- Version: <distro> (64-bit)
- Memory Size: 1024MB*
- New Virtual Disk:
- Type: VMDK (Dynamically allocated)
- Max Size: 40GB
Modify the VM’s settings:
- Disable audio
- Disable USB
- Ensure Network Adapter 1 is set to NAT
- Add a port forwarding rule as follows:
- Name: SSH
- Protocol: TCP
- Host IP:
- Host Port: 2222
- Guest IP:
- Guest Port: 22
- Mount the Linux distro ISO
VMware Fusion #
Create a new Virtual Machine with the Assistant:
- Select “Continue without disc”
- Select “Choose a disc or disc image…”
- Locate the ISO for the distribution you want to install, then select “Open”
- Unselect the checkbox for “Use Easy Install”
- Choose “Customize Settings”
- Enter a name for the VMware file and select “Save”
Customize the VM’s settings:
- Turn on Shared Folders
- Change the Networking to Internet Sharing > Share with my Mac (aka NAT)
- Change the disk size to 40 GB and deselect “Split into 2GB files”
- Turn off the sound card
- Turn off “Share Bluetooth devices with Linux”
Installing the Guest OS #
Boot the VM, install the Guest OS and customize the following settings when prompted:
- Host Name: vagrant-<distro><arch>
- Root Password: vagrant
- Full Name: vagrant
- User: vagrant
- Password: vagrant
Setting up the Guest OS #
These are the minimal set of steps to get your Guest OS off the ground. I personally recommend not polluting your box with extras if they’re not necessary. Additional software packages can be added by a provisioning tool. This allows your base box to be reusable across projects or teams.
Update the sudoers file #
The vagrant user will be doing all the work for us. The vagrant user requires password-less sudo privileges and needs to run without a tty (a terminal).
As most Linux distros only assign the root user to the sudoers group we must add our vagrant user to the sudoers file. We’ll have to do this as root
$ su -
$ visudo
Ubuntu distros will add the user created during the installation to the sudoers list. While the user has sudo permission we still need to change the settings.
Add or modify the following lines where necessary:
Defaults:vagrant !requiretty
#Defaults !visiblepw
Defaults env_keep = "SSH_AUTH_SOCK"
vagrant ALL=NOPASSWD: ALL
Save the changes and exit your editor. Exit the root shell if necessary. The vagrant user should now be able use sudo without a password. Validate this by running the following command in Terminal:
$ sudo pwd
Update packages #
It is recommended to update your installed packages at this point.
RHEL6 #
$ sudo yum update -y
Debian #
$ sudo apt-get upgrade -y
Once the updates have completed, restart your VM to ensure the updates are correctly applied. The following command in Terminal will restart the VM immediately:
$ sudo shutdown -r now
Download Vagrant’s insecure key #
Our vagrant user will use a SSH key to obtain authorized access to the box.
$ mkdir -p /home/vagrant/.ssh
$ chmod 0700 /home/vagrant/.ssh
$ wget --no-check-certificate
https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub
-O /home/vagrant/.ssh/authorized_keys
$ chmod 0600 /home/vagrant/.ssh/authorized_keys
$ chown -R vagrant /home/vagrant/.ssh
Install and configure OpenSSH Server #
The vagrant user will access and configure the box via SSH.
RHEL6 #
$ sudo yum install -y openssh-server
$ sudo chkconfig sshd on
Debian #
$ sudo apt-get install -y openssh-server
Edit and update the OpenSSH Server configuration.
$ sudo vi /etc/ssh/sshd_config
Add or modify the following lines:
Port 22
PubKeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
PermitEmptyPasswords no
PasswordAuthentication no
Save and exit the file. Restart the SSH service.
RHEL6 #
$ sudo service sshd restart
Debian #
$ sudo service ssh restart
Installing Guest Tools #
The Virtual Machine guest tools provide performance enhancements and improved management of the Guest OS. Guest Tools are also used by Vagrant to create shares between the Host and Guest OS'.
Prior to installing our Guest Additions, or VMware Tools, we require additional development packages for the tools to properly compile and install.
RHEL6 #
$ sudo yum install -y gcc make kernel-devel
Debian #
# Server
$ sudo apt-get install -y gcc build-essential linux-headers-server
# Desktop
$ sudo apt-get install -y gcc build-essential linux-headers-$(uname -r)
Next install the Guest Tools for our VM package.
VirtualBox #
Begin by mounting the Guest Additions. Select Devices > Install Guest Additions… from the menu bar menu.
$ cd /media/VBOXADDITIONS_4.2.12_84980
$ sudo ./VBoxLinuxAdditions.run
$ sudo umount /media/VBOXADDITIONS_4.2.12_84980 | cd ~
VMware Fusion #
Begin by mounting the VMware Tools by selecting Virtual Machines > Install VMware Tools from the menu bar menu.
$ sudo mkdir -p /mnt/cdrom
$ sudo mount /dev/cdrom /mnt/cdrom
$ tar xzvf /mnt/cdrom/VMwareTools-9.2.2-893683.tar.gz -C /tmp
$ cd /tmp/vmware-tools-distrib/
$ sudo ./vmware-install.pl
Cleaning Up #
Before we package up our box we want to clean up the box to minimize it’s size.
RHEL6 #
$ sudo yum clean all
Once we are satisfied with the state of the VM, shut it down to prepare it for packing.
$ sudo shutdown -h now
Packing our box #
Packaging up the VM will create the .box file described earlier. [tabbed_section][tab title=“VirtualBox” id=“t85” active=“true”]
The directory where the vagrant package command is executed is where Vagrant will create the .box file. If you have a specific location where you want this box to be created you should change to that directory prior to running the vagrant package command. The example below we package a CentOS guest.
$ mkdir -p ~/workspace/centos64/
$ cd ~/workspace/centos64/
$ vagrant package --base vagrant-centos64
VMware Fusion #
VMware Fusion requires a bit more manual process to package our VM. In Terminal:
-
Navigate to the location of your vmwarevm. By default this location is ~/Virtual Machines/.
-
Right-click the .vmwarevm file and select Show Package Contents
-
Create a file named, metadata.json, and enter the following contents:
{"provider": "vmware_fusion"}
- Create a file named, Vagrantfile, and enter the following contents:
# -*- mode: ruby -*-
# vi: set ft=ruby
Vagrant.configure("2") do |config|
config.vm.provider :vmware_fusion do |v, override|
v.gui = true
end
end
- We next want to optimize the box to reduce it’s size:
$ /Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager -d Virtual Disk.vmdk
$ /Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager -k Virtual Disk.vmdk
- Finally compress the box:
$ tar cvzf package.box ./*
Test starting the box #
$ vagrant box add testbox package.box
$ vagrant init testbox
$ vagrant up
Vagrant up will output the following if your box was successful.
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'testbox'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Configuring and enabling network interfaces...
[default] Mounting shared folders...
[default] -- /vagrant
To login to the Guest from our Host we can run:
$ vagrant ssh