As a developer in a small company, there is lot of what I have to do that is not related with typing code. Seems like these days I spent a lot of time taking care of “our little server garden”. Some of the flowers we put there required quite a lot of attention. We also had some issues with our automatic watering system 😉
And even when your water system is perfect there are times when you just have to go and dig up some flower, so another – more beautiful and easier to care about will take its place. This blog post is about one of those cases. It was time to upgrade our application servers.
Big part of our code is Java, so the core of our systems is deployed over JBoss servers using Java 7. For our new infrastructure we wanted Java 8 and latest JBoss server release. When I started working on the task, immediately asked myself the question – how do I test it?
- I did not have an extra machine to experiment with
- I did not want to play on a production server
- I did not want to pollute my developer machine with multiple Java and Application servers instances
- I also had to develop a script that will provision a fresh new machine with exactly same configuration
We have provisioning scripts for all our servers, even a basic one for what I was trying to accomplish. Basic was not good enough and I needed to play with it a bit – something I did not want to do on our Linux servers.
Obviously I needed a Virtual Machine
I have experience with Virtual Box, but working with Virtual machines was not something I as looking forward to. IMHO they are not convenient and require more attention that I like to put.
What I need is a quick and easy way to set a machine from a clean installation. Our production servers are virtual machines that use the same OS and similar “hardware”. Difference is on what is installed and as I mentioned we have the install scripts for each of them in a repo.
Luckily one of my colleagues was using Vagrant and convinced me to try it out. It sounded easy, convenient and just what I needed.
Vagrant at a glance
Vagrant will take some small configuration as an input and do all the work required to set up a working virtual machine for you – with port forwarding, ssh access, synced folders. You can also provide a provisioning script of your choice. By default it will set everything up using Virtual Box as provider, but you can choose others – even Docker!
Setup time
I am a Mac user and use Homebrew, so everything was pretty fast (prepare to provide a password for Virtual Box install):
brew cask install virtualbox
brew cask install vagrant
It is pretty simple for Linux as well. Windows – no idea, probably harder 🙂
Next step is optional, in case you want a fancy UI to manage your machines. You can use Vagrant Manager (OSX only).
brew cask install vagrant-manager
Once all that is completed you can just open your terminal, create a folder and init your new Vagrant machine with one command:
vagrant init debian/jessie64
What this does is create a basic Vagrant configuration for a vanilla debian/jessie64 installation. It all resides in a file named Vagrantfile
in the same folder where you issued the command.
Here is a list of available machines can be found on Vagrant Cloud.
You can optionally add a box that you want to use, but it is not required. When you start a machine for the first time it will be issued if needed:
vagrant box add debian/jessie64
Time to fire it up!
vagrant up
That’s it! All this executed for less then 10 minutes on my machine. Depending on your internet connection it could be even faster.
But how do I access it? Simple:
vagrant ssh
Vagrant will by default bind port 22 on the guest machine to port 2222 on the host. So you can just ssh / scp to port 2222 on localhost if you want.
Unveiling some of the Magic
Configuration
Initial Vagrantfile
(created when you made that init) is pretty well documented. Lets take a brief look anyway.
Its written in Ruby:
# -*- mode: ruby -*-
You can change the box here:
# Every Vagrant development environment requires a box. You can search for
# boxes at https://atlas.hashicorp.com/search.
config.vm.box = "debian/jessie64"
You can setup some basic port forwarding:
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080
You can also write your provisioning script here:
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# sudo apt-get update
# sudo apt-get install -y apache2
# SHELL
For simple installations writing the commands here works, but IMHO it is better to put those in a separate script:
config.vm.provision "shell", path: "install-script.sh"
You can even pass arguments!
config.vm.provision "shell", path: "install-script.sh", args: "/vagrant"
Working example
My efforts to create two machines for JBoss 7 and Wildfly installations are in this Github repo.
Some key notes:
1. I have set up port forwarding from 8080 on guest machine to 8080 on host machine
2. For this to actually work JBoss/Wildfly servers are both bound to address 0.0.0.0. If you just use localhost this will not work.
3. Vagrant will, by default, sync everything in the folder where Vagrantfile
resides to /vagrant
folder. Sync will happen on startup only (at least on OSX by default). You can trigger it manually using vagrant rsync
or even make it automatic by running vagrant rsync-auto
.
4. I have deployed a simple hello-world-servlet to test port forwarding is ok
How about sharing your VM?
One of the cool features of Vagrant is sharing your VM with outside world. Its pretty easy:
1. You set up port forwarding in Vagrantfile
:
config.vm.network "forwarded_port", guest: 80, host: 8080
You do not have to specify port 80. Vagrant will search for ports that can be shared and try to use that. I have used 8080 in my repo.
2. You register at Hashicorp Atlas (its free)
3. You run vagrant share
In those 3 simple steps you get URL everybody can connect to.
You can even set it up so other developers can actually ssh to your machine! Very useful for working with others.
I am done here, how do I kill it?
You can use vagrant destroy
to completely destroy the VM or just vagrant halt
to stop it for now.
And thats not all
I have used Vagrant as a quick way to create environment I can play with, but that is not all. As a developer, I can use folder sync and port forwarding to set up preconfigured developer environment I can easily share with others. Just think about how quickly you can onboard new people to your project. No more complicated setup – vagrant up
is all you need.
Epilogue
Vagrant really helped me to take better care of “our little server garden”. I hope others also find it useful.
Thanks for reading!