Run Ubuntu within OSX using Vagrant
How (and why) to run ubuntu seamlessly on OSX for c++ development
How (and why) to run an ubuntu development environment within OSX
Rambling
In this tutorial, I'll show you how to run a full linux workstation within OSX, offering a seamless transition between separated c++ and web development environments.
I'm a software developer working in C++11, compiling certain endpoints into node.js packages and providing them to the node.js backend team within my company. Like most js developers I use a macbook, and like most C/C++ developers, I use a linux workstation.
I use OSX for its delightful homebrew package manager, its beautiful user interface, and of course, cafe cred with the local hipsters.
Linux (Ubuntu 14.04 LTS) I use for its lack of abstraction, its similarity to production environments, and perhaps most importantly, the satisfying mixture of mixing three ~5yo monitors with my favourite clicky keyboard.
The issue comes when I want to work away from my desk, whether that be at a cafe, in a break-out area at work, or whilst travelling. I knew that what I needed was a linux laptop, however like most macbook users, I was less than willing to trade my macbook in for another machine. Having successfully used KVM and other hypervisors before, I decided to pursue a hypervised linux desktop within OSX.
The particular goals I had included:
- The ability to somewhat serialize my desktop environment.
- A GUI
- The ability to effortlessly expose ports to the host machine
Having used vagrant once or twice to perform isolated analysis of potentially malicious code, and having been surprised by its performance, I decided to see what I could do to get it running with a GUI. I was genuinely surprised by how simple it was.
What is vagrant?
Vagrant is a tool for building and reducing the setup time of complete development environments. It allows you to specify how much of your physical or host machine's physical capacity should be allocated to the VM, what software packages should be installed on the VM, and what other tasks should be performed on setup. You can run any bash command from within vagrant, including cloning git repos.
How
Install Vagrant
Unfortunately Vagrant removed their dynamic installation URL, so you'll have to head over to the vagrant website and download the installer.
Follow the prompts as expected. The nice part here is that the installer will automatically add vagrant to your system path so that it is available terminal via the vagrant command.
Now all you need to do is initialise vagrant with an image that supports a GUI (I'll give you one here) and you're up and running.
mkdir ~/linux
cd ~/linux
vagrant init arxisos/ubuntu-trusty-gui
Before you get carried away though, you should have a look at the vagrant file. I'll show you a copy of that now, and give you a break down.
The Vagrant File
# -*- mode: ruby -*-
# vi: set ft=ruby :
#This is a bare bones vagrant file, stripped down to launch a vagrant box on virtual box, expose port 80 to your host, and execute some bash commands to setup your workstation. For more detail, please see https://docs.vagrantup.com.
# Configuration of vagrant is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Don't change this unless you know what you're doing (hint: if you're reading this post, you don't!)
Vagrant.configure(2) do |config|
# Every Vagrant development environment requires a box. You can search for other
# boxes at https://atlas.hashicorp.com/search.
#This is the box you should used to support GUI
config.vm.box = "arxisos/ubuntu-trusty-gui"
#This forwards port 80, and makes it accessible at localhost:8080 on the host machine. Super handy for emulating webservers.
config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.10"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder.
config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = true
#
# Customize the amount of memory on the VM:
vb.memory = "4096"
end
# Enable provisioning with a shell script.
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install -y apache2
sudo apt-get install -y build-essential
SHELL
end
Specify the image to use
Every vagrant box needs an image. You can browse those at hashicorp.
# Every Vagrant development environment requires a box. You can search for other
# boxes at https://atlas.hashicorp.com/search.
#This is the box you should used to support GUI
config.vm.box = "arxisos/ubuntu-trusty-gui"
Forward port 80 to host, and specify an IP for host-only access
#This forwards port 80, and makes it accessible at localhost:8080 on the host machine. #Super handy for emulating webservers.
config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.10"
Create a shared folder between the host and the VM
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder.
config.vm.synced_folder "../data", "/vagrant_data"
Configure the provider (in this case, Virtual Box)
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = true
#
# Customize the amount of memory on the VM:
vb.memory = "4096"
end
Setup your provisioning
This is where you can setup your environment.
Using standard bash commands (don't forget to use -y to trigger boolean queries, and provide passwords or (preferably) an ssh key for authentication. Your VM's username and password are 'vagrant'
# Enable provisioning with a shell script.
#Other provisioning options such as puppet, chef, ansible and docker are available for
#vagrant. Here we'll just use standard bash commands.
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get install -y apache2
sudo apt-get install -y build-essential
SHELL
end
Why
Now you can seamlessly transition between your C++ workspace on linux and your js workspace on OSX as in this video on my twitter feed
I hope you found this walkthrough useful. Let me know of anything else you did to streamline your new portable, virtualised linux workstation below.
Until next time,
Jordan
TLDR;
CTO Nova Eye Medical, building current and future generation devices to treat the world's leading causes of blindness. Background in Artificial Intelligence and Capital Markets, Lover of Business, Technology and Markets