Over a million developers have joined DZone.

Installable Vagrant Boxes

DZone's Guide to

Installable Vagrant Boxes

· Agile Zone ·
Free Resource

Whatever new awaits you, begin it here. In an entirely reimagined Jira. 

We distribute vagrantbox to people demo-ing our project. It is a hassle to install the whole setup for non-IT people The following is a proof of concept to make a self installing vagrant machine.

To create the box you need:

  • jruby installed

To run the box:

  • You need to have Virtualbox installed
  • And Java running on the machine
  • on windows machines you need to comply to vagrant windows rules (64bit)

Get Jruby and all the gems installed

$ rvm install jruby
$ rvm use jruby
$ mkdir shrinkwrap
$ cd shrinkwrap
$ cat <EOF > Gemfile
source 'http://rubygems.org'

gem 'vagrant', '0.7.2'
gem 'warbler'
gem 'sinatra'
gem 'jruby-openssl'
gem 'jruby-win32ole'

$ gem install bundler
$ bundle install

Prepare the vagrantfile

We create a simple vagrantfile that downloads a box running ubuntu

$ mkdir lib
$ cat <EOF > lib/Vagrantfile
Vagrant::Config.run do |config|
  config.vm.box = "shrinkwrap"
  config.vm.box_url = "http://opscode-vagrant-boxes.s3.amazonaws.com/ubuntu10.04-gems.box"
  config.vm.boot_mode = :gui
  config.vm.customize do |vm|
          vm.memory_size = 384
          vm.name = "Shrinkwrap"
  config.vm.forward_port "http", 80,  9000

Add Sinatra in the mix

To give the user a gui to start the vm, we provide a simple URL using sinatra

$ cat <EOF > lib/shrinkwrap.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
require 'vagrant'
require 'vagrant/cli'
require 'pp'

class Shrinkwrap < Sinatra::Application 
  get '/up' do
    body "We do an up"
        puts "we are loading the config file"
        @vagrant_env=Vagrant::Environment.new(:cwd => vagrant_dir)
        pp @vagrant_env
        puts "we are uping the machine, please wait..."
        Vagrant::CLI.start(["up"], :env => @vagrant_env)
        body "We are up"

$ cat <EOF > config.ru
require "lib/shrinkwrap"
run Shrinkwrap.new


Package the Sinatra project with warbler

Warbler allows you to package sinatra projects. It packages a jruby version inside the warfile so it only needs java installed.

To package the current sinatra, just run in the directory where you created the config.ru file

$ warble

should result in a shrinkwrap.war

Make the warfile executable

Next step is to make the warfile executable. Similar to jenkins we want to execute a war file. Winstone is the tool that makes it possible

Now can use winstone to make the warfile a selfcontained executable. For windows we need to package the "jruby-openssl","jruby-win32ole" so we create a warble config file.

We embed our previous create war file inside the warbler jar by first extracting it, adding it as embedded.war and packaging it back again.

$ mkdir config
$ cat <EOF > config/warble.rb
Warbler::Config.new do |config|
     config.gems += ["jruby-openssl","jruby-win32ole"]
$ wget "http://sourceforge.net/projects/winstone/files/winstone/v0.9.10/winstone-0.9.10.jar/download"
$ mkdir extract
$ cd extract
$ jar -xvf ../winstone-0.9.10.jar
$ cp ../shrinkwrap.war embedded.war
$ jar cvfm ../ubuntu10-04.jar META-INF/MANIFEST.MF .
$ cd .. 


Ready for take off

now you can start the newly create warfile with

$ java -jar ubuntu10-04.jar

And when you surf to http://localhost:8080/up . It will download the box from S3 and after sometime you should see the virtualbox spinup!


Point proven. I think this concept has a large potential, you just download the self-executable jar and poof, you have the environment installed. Mix this with a market place for VMs or vendors packaging demo of their products.

In a nutshell! The future is here :)

I'd be interested to hear how you would use this idea in your daily life!

Now on to the next idea!

Further reading

New roadmaps, more flexible boards, and dozens of new integrations. And that's just the beginning.  


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}