Skip to main content

Creating a Custom Vagrant Box from Scratch

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:

  1. Navigate to the location of your vmwarevm. By default this location is ~/Virtual Machines/.

  2. Right-click the .vmwarevm file and select Show Package Contents

  3. Create a file named, metadata.json, and enter the following contents:

{"provider": "vmware_fusion"}
  1. 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
  1. 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
  1. 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