Creating a Vagrant Base Box - CentOS

Building a Vagrant Base Box - v1.1 onwards (API v2) - CentOS 6.6

For this guide, I'll assume you are up and running with Vagrant, and are vaguely family with the various commands.

Vagrant is a way to create and reproduce development environments easily. The basic idea being that you can create a local environment identical to your live environment. Allowing you to develop, test, debug then run all on the same environment. It also enables you to keep your own machine free from certain development tools.

Vagrant requires something called a base box, this is the base operating system that you use on your project. The base box should include the OS and a few other tools. Vagrant comes with an Ubuntu flavoured box which you can start using straight away:

mkdir vagrant-test
cd vagrant-test
vagrant init

However, we use Amazon Linux as it works flawlessly on AWS (as you would expect). I've heard that Amazon Linux is a hybrid of RedHat, CentOS 5, CentOS 6 and some custom stuff – but I cannot find where I heard that – so it might not be 100% accurate. However, that means our closest OS to this is probably CentOS 6, so we will create a Vagrant CentOS 6 base box (CentOS 6.6 at the time of writing).

Download the latest minimal installation ISO from one of the mirrors:

http://anorien.csc.warwick.ac.uk/mirrors/centos/6.6/isos/x86_64/CentOS-6.6-x86_64-minimal.iso

Open up VirtualBox, create a new virtual machine:

Name: CentOS 6.x Minimal (Or whatever you want to name it)
Type: Linux
Version: Red Hat
RAM: 450MB*
Select, "Create a new virtual hard drive now"
Select a VMDK (Virtual Machine Disk)
Dynamically sized
Leave the name and set the size to 30GB

* 360MB recommended by Vagrant, but CentOS claim the installer needs 392MB to run – but I can't get it running with 392MB.

Start the new virtual machine

When prompted, select the ISO you downloaded as the start up disk – select “Install or upgrade an existing system”.

Follow through the onscreen steps (if you test the media, the Virtual Machine ejects the disk image – just click the CD icon on VirtualBox and select the image).

If you are distributing the box – set the root password to vagrant

System Configuration

Once your virtual machine has installed CentOS and booted up, login and we can begin the configuration.

First enable networking, as it's disabled by default in the minimal installation.

vi /etc/sysconfig/network-scripts/ifcfg-eth0

Remove the HWADDR line, set ONBOOT=yes and NM_CONTROLLED=no so you are left with:

TYPE=Ethernet
UUID=(your uuid here)
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=dhcp

Also edit, /etc/udev/rules.d/70-persistent-net.rules remove the ADDR{address}==”...”:

SUBSYSTEM==”net”, ACTION==”add”, DRIVERS==”?*”, ATTR{type}==”1”, KERNEL==”eth*”, NAME=”eth0”

Ok, now lets restart the network service to apply our changes:

service network restart

Test the network by pinging your favourite site

ping google.co.uk

Installing VirtualBox addons

Firstly, we want to update the kernel packages to the latest version.

yum update kernel*
yum install -y gcc make perl kernel-devel kernel-headers

Some people seem to be able to install the addons now (without the command below, or using yum install kernel-headers kernel-devel), but I seem to come across errors in the latest CentOS – the virtual additions log stated that KERN_DIR didn't point to a directory (which it did). But it turns out it's because the kernel headers being used are a different version to the ones installed. So run;

yum install -y kernel-headers-$(uname -r) kernel-devel-$(uname -r)

This installs the correct headers for the version you are running.

You'll also need to install DKMS, without this your Vagrant box will fail to mount folders (Vagrant error: Failed to mount folders in Linux guest):

cd /tmp
curl -O http://linux.dell.com/dkms/permalink/dkms-2.2.0.3-1.noarch.rpm
yum install dkms-2.2.0.3-1.noarch.rpm

Ok lets move on to the VirtualBox Additions

On VirtualBox click 'Devices' then 'Install VirtualBox Additions'. This adds the virtual box additions to the virtual machine To mount the ISO;

mkdir /media/cdrom
mount /dev/cdrom /media/cdrom
export KERN_DIR=/usr/src/kernels/$(uname -r)
/media/cdrom/VBoxLinuxAdditions.run --nox11

The only one to skip should be the Windows System drives (because we are not using a GUI). To verify everything has worked, you should get version numbers back from the following:

VBoxControl --version
VBoxService --version

Setting up Vagrant

You can't go wrong reading the official docs (https://docs.vagrantup.com/v2/boxes/base.html).

Hostname

vi /etc/sysconfig/network

Set you hostname to vagrant-centos

Vagrant User

Ensure sudo is installed

yum install -y sudo

Add vagrant user, add to the wheel group and set their password to 'vagrant' (this is required for Vagrant to work)

useradd -m -G wheel vagrant
passwd vagrant

Next we are allowing the vagrant user passwordless sudo access.

echo "vagrant ALL=(ALL) ALL" >> /etc/sudoers
echo "%wheel ALL=NOPASSWD: ALL" >> /etc/sudoers
echo 'Defaults env_keep="SSH_AUTH_SOCK"' >> /etc/sudoers

Comment out the line Defaults requiretty:

vi /etc/sudoers

SSH

If you are distributing the box, then you should included the Vagrant insecure SSH keys – this allows anyone to use your box. However, remove these keys if you are not distributing the box.

mkdir ~vagrant/.ssh
curl -L https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub > ~vagrant/.ssh/authorized_keys
chown -R vagrant:wheel ~vagrant/.ssh
chmod 0700 ~vagrant/.ssh
chmod 0600 ~vagrant/.ssh/authorized_keys

What we do here is create the necessary directory, download the insecure public key and add it to the vagrant users list of authorized_keys. We then set the correct owner and permissions on these.

Basic software for Vagrant

Vagrant mentions you can install Puppet and/or Chef - allowing the box to be provisioned. This step is optional, but recommended. We are going to install:

  • Ruby
  • RubyGems
  • Puppet
  • Chef

Ruby and RubyGems

I've found the best way to get up to date versions of Ruby is using a ruby version manager (RVM). You can also use the RBEL repository, but the repositories are usually a few version behind.

Using the docs from Ruby (http://www.ruby-lang.org/en/downloads/):

curl -L https://get.rvm.io | bash -s stable –-ruby

When that's done, as the instructions say, run

source /usr/local/rvm/scripts/rvm

If all has gone well, run

ruby --version

Mine returns 2.1.5p273 at the time of writing.

Ruby gems should also be installed;

gem --version

Puppet

The easiest way to get Puppet (and the recommended one) is to grab it from the EPEL repo, however this downloads an older version of Ruby. Which we don't really want, so we will use the gem installer; which is straight forward but involves a bit of config.

gem install puppet --no-rdoc --no-ri
groupadd puppet
useradd -s /sbin/nologin -g puppet puppet
curl -L https://raw.github.com/puppetlabs/puppet/master/ext/redhat/client.init > /etc/init.d/puppet
chmod +x /etc/init.d/puppet
mkdir /etc/puppet
touch /etc/puppet/puppet.conf
cp /usr/local/rvm/gems/ruby-2.1.5/gems/puppet-3.7.3/conf/auth.conf /etc/puppet/auth.conf

(Your path on the last command will change with the different ruby versions)

puppet --version

Chef

Again there is an easy way to do this using an install script from Opscode. But, it doesn't take the Ruby from the RVM. So:

gem install chef --no-rdoc --no-ri
knife –version

SSH Tweak

As recommended in the official documentation, we are going to disable the SSH DNS lookup.

Uncomment #UseDNS yes and change to UseDNS no.

vi /etc/ssh/sshd_config

Packaging the Box

Remove documentation, remove yum cache, clear our bash history

yum clean all
history -c
cat /dev/null > ~/.bash_history

Shutdown the virtual machine

shutdown -h now

Finally, lets package the box

vagrant package --base "CentOS 6.x Minimal"

That will then create a package.box file in your current directory.

Using the Box

Firstly, we need to tell vagrant to add this box.

vagrant box add centos6-base package.box

Now, create a directory for a new project that we are going to use this vagrant box in.

mkdir ~/Projects/Vagrant-Test
cd ~/Projects/Vagrant-Test

Initialise Vagrant (creating a Vagrantfile in the current directory), then launch our box.

vagrant init centos6-base
vagrant up

You will then see the output of Vagrant, copying your box, then booting into it. When this is complete you should then be able to login to the box with:

vagrant ssh

Finishing up

That should be you up and running with your own CentOS base box for Vagrant. Taking this further I would recommend looking into provisioning to build the server. Ideally you would provision your Vagrant boxes and live servers in exactly the same way (this gives you near identical set up locally for development and live). If you get the provisioning right, anyone can download your project, run 'vagrant up' and be running an identical environment for development - pretty handy.

Also note that Vagrant Cloud launched more recently - it offers a really easy way to browse and use trusted and top-used boxes from the community.

Any problems or questions let me know in the comments and I'll do my best to assist.