Working with and Customizing Virtualboxes with Vagrant
I have been getting more into Vagrant and Virtualboxes recently. When I figured out how to script vagrant, I started to create custom environments for every project I work on. github repo
Having a custom vagrant file with each project has been beneficial:
- I can instantly recreate each project’s environment instantly.
- Other users of my projects can instantly recreate my project environment, without my involvement.
- This setup can save valuable time, letting others focus on programming, not on the project’s configuration.
This article will go over Virtualbox and scripting Vagrant for a consistent developer experience.
We will cover:
- overview of vagrant and virtualbox
- interacting with the “computer” created by vagrant
- scripting vagrant to setup virtual “computers”
Do you remember the steps to install your favorite programming langauge? How about any accompanying frameworks?
How about the newest version of your tools, like editors, syntax checkers, source control?
For example, the installed version of Python in Ubuntu 14.04 is 2.7.6. To install 2.7.13, this is just one set of instructions:
- Install the python-software-properties package
- Install common Python build tools list here
- Download Python 2.7.13 source
- Configure and Install Python 2.7.13 source
To install the latest supported version of NodeJS, this is one set for Ubuntu:
- Get & Setup NodeJS repository information for the system
- Update software repository listing
- Install NodeJS
- Install NPM for the whole system
Each of those are at least four steps and can take a variable amount of time for each step. Getting it done once is a lot of work.
When you want to share your creation with another, or have an new team member join the project, do you remember all the steps taken to setup the software environment? Can you take time out to set up theirs?
Instead of looking up or manually installing and configuring a system, write to script Vagrant to automatically create the system.
Setup a system once using a script, then share the script with anyone that needs to have the same environment.
This way, all
- new team members download the script and run to get the same software environment as yours
- there’s dependency issues with varying versions (i.e. Python 2 vs Python 3)
- deliver software consistently
This is an open source software tool that manages virtualized environments, like Virtualbox. It’s open-sourced and managed by Hashicorp.
This is an open source software tool that creates an emulation layer inside another computer. The emulation layer allows for an operating system to be installed on it.
Virtualbox allows a single hardware computer system to operate multiple software computer systems at once. Just like having multiple applications open at once.
The operating system that Virtualbox and Vagrant runs on. It is hosting other operating systems inside itself.
This is also known as Host Operating System, as Virtualbox builds its emulation layer on it.
The operating system that is run by Virtualbox and managed by Vagrant.
This is also known as Guest Operating System, as the operating system that is a guest to the host.
Think of both in terms of a friend visiting you. You are the host because you know more about the area. Your friend is the guest, as they depend on you for information.
Required system resources depend on the guest OS requirements.
I will be using Ubuntu 14.04 (Trusty Tahr) that have requirements of:
- 1GB of free storage space
- 512MB of available RAM
I recommend more, and probably
- free storage space >3GB recommended
- system RAM >2GB (more is better)
To install Vagrant, download the appropriate installer from here and follow the instructions.
Vagrant is installed when in a terminal, running
returns a value, ideally > 1.9
With vagrant, VirtualBox is install automatically. This is the homepage of the virtualbox project.
Setting up a new guest OS
These are the steps to setup Ubuntu as a guest OS on your computer.
The scripts I discuss are available at: https://github.com/a-leung/vagrant_shell_provisioning
Each guest OS created by vagrant lives inside a directory on the host system. To setup new virtual machine with vagrant:
( host )$ mkdir new_development_machine
( host )$ cd new_development_machine/
To create a new guest OS with vagrant, a Vagrantfile is used to control the guest OS settings.
Create a file named:
Vagrantfile in the
directory with the following contents:
"2"refers to use version 2 of the configuration format
config.vm.boxrefers to which version the guest operating system vagrant to install, in the above case, the guest operating system specified is Ubuntu 14.04, Trusty Tahr.
So far, with the directory and Vagrantfile, there is no guest OS to
work with. To have Vagrant start building the guest operating system,
run the following command in the same directory where the Vagrantfile
The expected output is:
This does a lot of work:
- vagrant downloads the guest operating system (Ubuntu 14.04) from cloud servers (~200MB)
- setups Virtualbox with guest computer settings
- installs the operating system in Virtualbox
- sets up the operating system with credentials
The longest part of this process will be downloading the guest operating system. Once it is downloaded, vagrant saves it to the host computer to be reused in the future guest operating systems.
Accessing the Guest Computer
With a new guest computer inside the host computer, how do we access it?
The easiest way is to login to Ubuntu using SSH, secure shell. Vagrant
has preconfigured SSH with keys in the
vagrant up process.
To login to the guest computer from the same directory as the Vagrantfile:
From here, commands can be run. If there is anything to be installed
that requires superuser/root access, prepend:
sudo to the command. For instance, to install Emacs:
Accessing Files on Guest Computer
To share files between the guest system and host system, vagrant
configures the current host computer’s folder (in this article,
new_development_machine/ is used) to be shared on the guest computer
Now the guest computer is set up for basic operation, it can be used as
is like a regular computer. Software can be installed, removed, files
shared between the host and guest through the
Vagrant has a ‘provisioning’ system that sets up the guest OS according to a script.
I have found vagrant’s provisioning system drastically improves the development experience because it:
- installs specified software
- allows configurations to be shared through source control
- allows computer to be destroyed and re-created with the same settings
I will go over how to use vagrant’s shell provisioner.
The shell provisioner is very simple: putting any commands that would be typed in the command line will be executed by the shell provisioner.
The shell provisioner is run as root, so
sudo is not needed for any
commands in the shell provisioner.
If a command requires an answer from the user, like above when
installing Emacs, the shell provisioner will fail. So, ensure commands
in the script do not require an answer by adding an option to say
-y for apt-get.
Let’s try this by starting with a simple script that writes the current date and time to a file. Modify the Vagrantfile so it is like below:
config.vm.provisiontells vagrant to configure the system after initial installation.
"shell"tells vagrant to use the shell provisioner.
:inline =>tells vagrant to use the included shell script starting on this line.
SHELLare delimiters to indicate the section between them are shell scripts.
To try it out, run
$vagrant destroy then
$vagrant up. Let’s start
with a newly installed guest computer.
Example: Installing Python
Let’s write a script to install a newer version of Python every time a new computer is created by vagrant:
First, let’s check what version of the Python programming langauge is currently installed:
Change the Vagrantfile to have the following contents.
There are comments inline (those with a
# in front) to explain the
Example: Install node
On Ubuntu 14.04, Node.js is not installed by default:
Using the version of node included is a bit old (v0.10.25), which is pretty old by today’s standard, so let’s configure the shell provisioner to install the latest version.
To get rid of a guest computer, the easiest way is to run
( host )$
vagrant destroy from the host computer directory with the
This will remove the guest computer completely from the system. If
there are any files on guest computer not in the
they will be destroyed.
Where to go from here?
The vagrant shell provisioner documentation is useful.
- Using external shell script instead of inlining the script in the Vagrantfile.
- Using script arguments to customize the guest computer setup.
Other Guest OS
Other Guest OSes that are supported by Vagrant can be found
here. Just setting the
config.vm.box = 'vm box name' to use them. The current long term
support version of Ubuntu, 16.04, has a name:
Other Programming Languages
A repository of Vagrantfiles for many programming language setup.
The shell provisioner is powerful enough to get a single machine up and running for a developer. More sophisticated provisioners exist and vagrant provides a great way to explore them. These include:
Vagrant and virtualbox form a great basis to setup another computer inside your current computer to isolate and consistently create your development environments on other computers.
With Vagrant’s scripting feature, it is easier to get a consistent setup every time so the newest version of a programming language, like python or node, is setup consistently each time.
This is why I love having vagrant, it’s an easy way to consistently create the application’s environment.