Sie sind auf Seite 1von 17

Your Situation

This could be quite varied, you could be:


A solo developer looking for a fast/easy way to have a local dev environment that resembles your
production environment (say you develop on OS X, but are deploying to an infrastructure running
some distribution of Linux. As a bonus, there is also an easy way to deploy to Amazons EC2 if you
have a solid setup locally.
1.
A member of a team, where everyone has their own development style and want to avoid the
headaches of cross-platform support.
2.
Someone who normally sets up servers in a third-party hosting environment, but you want to test
your deployment without paying a bunch of money in wasted servers (this is where I am!).
3.
What is vagrant?
Vagrant (http://vagrantup.com/) is essentially a wrapper around a variety of virtual machine
providers. If you have ever used Make to build a piece of software, it is kind of like that except with
virtual machines. It provides a single command that uniformly creates, provisions, destroys, and
connects to machines. You can use many different VM providers, but I will be using VirtualBox because
it is free and easy to use. Usually it is a pain in the butt to create a virtual machine, install the operating
system, etc. Vagrant makes it super easy, and there are lots of premade boxes for you to use (more on
this later).
What is Puppet?
Puppet (http://puppetlabs.com) is an infrastructure automation tool and we are going to use it to take
the hard work out of setting up our systems. We can do this because lots of people have put a ton of
effort into writing modules that we can use. This wont be a tutorial on Puppet, but it will go over the
basics so that you can use modules that other people have written.
But l don't like/use Puppet!
That is fine. Thankfully Vagrant is flexible in its provisioners and you can read more about the
alternatives (http://docs.vagrantup.com/v2/provisioning/index.html). For simplicity I am just going
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
2 of 17 11/03/2013 10:25 PM
to cover Bash and Puppet since that is what I am familiar with. The overall process should be the same if
you decide to use Chef (http://www.opscode.com/chef/) or Ansible
(http://www.ansibleworks.com/), but because I dont know much about them, I wont discuss them
further.
Getting Started
lnstallation
Vagrant is a breeze to install: you can read over their installation instructions
(http://docs.vagrantup.com/v2/installation/index.html). Essentially, download the package that is
relevant for your platform of choice and install it in the way you would normally install a package.
You will also need to install your virtual machine provider, in my case VirtualBox
(https://www.virtualbox.org/).
First vM
Once it is installed, you will want to create a new project directory and initialize it.
$ mkd1r ~1varanl
$ cd ~1varanl
$ varanl 1n1l
This will create a new directory and get it ready with a file called Vagrantfile
(http://docs.vagrantup.com/v2/vagrantfile/index.html) which will contain all the information that
Vagrant needs to manage your dev environments.
In that file there will be a bunch of comments about the different things you can put in that file. For now
we just care about configuring a base box (http://docs.vagrantup.com/v2/boxes.html) (which is just
a virtual machine image) and some other machine properties. I ended up with a file that looked
something like this:
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
3 of 17 11/03/2013 10:25 PM
# -*- mode. ruby -*-
# v1. sel il=ruby .
varanl.coni1ure{"2"} do ]coni1]
# Every varanl v1rlual env requ1res a box lo bu1ld oii oi
coni1.vm.box = "puppellabs-prec1se64"
coni1.vm.box_url = "hllp.11puppel-varanl-boxes.puppellabs.com1ubunlu-serv
coni1.vm.hoslname = "developmenl.kloudless.vm"
coni1.vm.nelWork .pr1vale_nelWork, 1p. "192.168.33.10"
coni1.vm.nelWork .iorWarded_porl, uesl. 80, hosl. 8080
# v1rlualBox Spec1i1c Cuslom1zal1on
coni1.vm.prov1der .v1rlualbox do ]vb]
# use vBoxManae lo cuslom1ze lhe vM. Ior example lo chane memory.
vb.cuslom1ze |"mod1iyvm", .1d, "--memory", "1024"]
end
end
Here are the things that we configured so far:
coni1.vm.box: The name of the box that you are bringing up. 1.
coni1.vm.box_url: The location where Vagrant can look to download the box if you dont
already have a copy on your machine.The box that I chose is provided by Puppet Labs and doesnt
have any pre-installed provisioning software. This will be installed later as part of the bootstrapping
process so that it can always be up to date.
2.
coni1.vm.hoslname: The hostname of the VM. 3.
coni1.vm.nelWork .pr1vale_nelWork: The private IP address that the VM will have on the
private VM network.
4.
coni1.vm.nelWork .iorWarded_porl: The port labelled guest on the guest VM will be
accessible on the port labelled host on your machine.
5.
VM memory: I gave my VM 1GB because it seemed like it would be enough (Note: this is provider
dependent).
6.
Once you have the file in place you can create and provision your VM from the same directory:
$ varanl up
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
4 of 17 11/03/2013 10:25 PM
After that command finishes running, you will have a VM ready for you to connect and start messing
around with. You can access the machine via SSH using:
$ varanl ssh
You will now have a shell on your virtual machine as the varanl user. The user has passwordless
sudo access on the machine, it full fledged Ubuntu 12.04 LTS VM and you can do whatever you want!
This is great and all, but we want to make things more automated, so you will want to exit your SSH
session and get rid of the VM with:
$ varanl deslroy
Automating All the Things
As was talked about earlier, the nice thing about Vagrant is that it is really easy to offload the
configuration to an automated tool, in this case Puppet. Since our VM is pretty bare bones, there is some
extra work that we want to do to prepare it.
Bootstrapping
The box that I chose doesnt by default come with puppet installed on it, this was a deliberate choice to
make sure that I could use the same version I am using in production without having to change the box
all the time. As such we need to do a little extra work. Preparing the machine to be puppeted is
relatively straightforward and we are going to take advantage of the fact that you can use multiple
provisioners on a single machine. In order to use the shell provisioner we add the following lines to our
Vagrantfile before the final end:
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
5 of 17 11/03/2013 10:25 PM
# Enable shell prov1s1on1n lo boolslrap puppel
coni1.vm.prov1s1on .shell, .palh => "boolslrap.sh"
Then we create a file called boolslrap.sh in the same folder as our Vagrantfile that contains the
following:
#!1usr1b1n1env bash
sel -e
1i | "$EuT0" -ne "0" ] , lhen
echo "Scr1pl musl be run as rool." >&2
ex1l 1
i1
1i Wh1ch puppel > 1dev1null , lhen
echo "Puppel 1s already 1nslalled"
ex1l 0
i1
echo "Tnslall1n Puppel repo ior ubunlu 12.04 LTS"
Wel -q0 1lmp1puppellabs-release-prec1se.deb \
hllps.11apl.puppellabs.com1puppellabs-release-prec1se.deb
dpk -1 1lmp1puppellabs-release-prec1se.deb
rm 1lmp1puppellabs-release-prec1se.deb
apl1lude updale
#apl1lude uprade -y
echo Tnslall1n puppel
apl1lude 1nslall -y puppel
echo "Puppel 1nslalled!"
One important thing to notice is that the script is idempotent (meaning that it can be run multiple times
without having any bad effects), this is important because we can run the provisioners without creating
a new machine. Your virtual machine will now be ready to be controlled via Puppet!
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
6 of 17 11/03/2013 10:25 PM
Adding Puppet
Since we dont want to install Puppet on our host machine, bring up the VM and connect to it. Puppet is
already installed. We can do all of our initial Puppet configuration directly within the vm. By default,
the folder containing the Vagrantfile is shared on the virtual machine in the path 1varanl and this
will make a good location to store our puppet configurations. Once in that directory you will want to
create a skeleton of your puppet dir:
$ mkd1r -p puppel1{man1iesls,modules)
$ louch man1iesls1s1le.pp
From here we will want to install some puppet modules that will make setting up a basic LAMP server
easy (for now we will just keep everything on the same box). There are lots of different ways to install
puppet modules, but the most straightforward is using the way that is built into puppet:
$ puppel module 1nslall -1 1varanl1puppel1modules \
puppellabs1apache
$ puppel module 1nslall -1 1varanl1puppel1modules \
puppellabs1mysql
Now we will want to actually write a puppet manifest , so we will want to create /vagrant/puppet
/manifests/site.pp with the following:
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
7 of 17 11/03/2013 10:25 PM
node `developmenl.kloudless.vm` { # |1]
class { `mysql..server`. # |2]
coni1_hash => { `rool_passWord` => `herpderpderp` ),
)
1nclude mysql..php # |3]
# Coni1ur1n apache
1nclude apache # |4]
1nclude apache..mod..php
apache..vhosl { $..iqdn. # |5]
porl => `80`,
docrool => `1var1WWW1lesl`,
requ1re => I1le|`1var1WWW1lesl`],
)
# Sell1n up lhe documenl rool
i1le { |`1var1WWW`, `1var1WWW1lesl`] . # |6]
ensure => d1reclory,
)
i1le { `1var1WWW1lesl11ndex.php` . # |7]
conlenl => `>?php echo \`>p<Rello World!>1p<\` ?<`,
)
# "Real1ze" lhe i1reWall rule
I1reWall <] ]> # |8]
)
This describes how the server gets configured, the basic function is setting your vm with apache, mysql,
and php along with a test page. Here are some more details about the different parts:
The node definition is how we collect configuration for the machine, the label
development.kloudless.vm matches the hostname that we configured the vagrant box with.
1.
This statement uses the mysql class to install the mysql server and sets up the admin password for
the db as herpderpderp.
2.
That is how the php bindings for mysql get installed 3.
Those two lines install the apache server package and mod_php respectively 4.
We want an apache vhost where we can access our basic test application. 5.
This actually creates the directories where the vhost content will live 6.
That is our application! Right now it doesnt actually use the database, but it is a good example, we
can define the contents of the file inline relatively easily this way. We will replace this later.
7.
This is a way of realizing virtual resources which in this case configures your machines firewall 8.
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
8 of 17 11/03/2013 10:25 PM
rules.
Now that we have the puppet configuration ready, we need to have Vagrant use it. This can be done
easily by adding the following lines to your Vagrantfile after the shell provisioner lines:
# Enable prov1s1on1n W1lh Puppel sland alone.
coni1.vm.prov1s1on .puppel do ]puppel]
puppel.man1iesls_palh = "puppel1man1iesls"
puppel.man1iesl_i1le = "s1le.pp"
puppel.module_palh = "puppel1modules"
puppel.opl1ons = "--verbose --debu"
end
This just tells vagrant where to find the modules we installed and the manifest we wrote. So now you
are ready to varanl up. Once your box is built, you should be able to visit http://localhost:8080
(http://localhost:8080) and see the output of your test page.
With a few small adjustments, you could use this to develop a full blown php app. The adjustments you
would probably want to make are as follows:
Remove the index.php file block from the sites.pp file 1.
Change the webroot value in the vhost code block to be /var/www/app 2.
Configure a shared folder that apache can point to as the webroot. For example, if you have a folder
called app that contained your application and it is in the same directory as your Vagrantfile, you
would add the following line to the Vagrantfile:
coni1.vm.synced_iolder "app", "1var1WWW1app"
3.
Once those changes are made, you should be able to just run vagrant provision to update the settings
and you can start dumping your project files into the app directory and you should see those changes on
the vm.
Learning More
If you wanted a LAMP server to develop a php application, you dont really need to go any further.
Odds are, however, that you want to do something more than just this. If you want to run a more
complicated application you can do this pretty easily if you can find a module to do it. The specific
details of how you use a module depends on what it is, but the documentation is usually ok. If you want
to more seriously manage your dev box with puppet, you should do some more reading so you can use
the different modules people have written more easily. Here is some recommended reading :
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
9 of 17 11/03/2013 10:25 PM
The Learning Puppet Series (http://docs.puppetlabs.com/learning/index.html) 1.
Example42 Tutorials (http://www.example42.com/?q=Example42PuppetTutorials). They also
have a bunch of good modules you can use
2.
Puppet 3 reference manual (http://docs.puppetlabs.com/puppet/3/reference/) 3.
Hiera
If you are a more experienced puppet user, you might be familiar with Hiera and want to use it with the
modules/classes that you have written. It is pretty easy to do. First, change the value of puppet.options
in your Vagrantfile to verbose debug hiera_config /vagrant/puppet/hiera.yaml. Now you need to
populate that file with your hiera configuration, depending on how you are using it you might end up
with something like this:
---
.h1erarchy.
- common
.backends.
- yaml
- puppel
.yaml.
.dalad1r.
1varanl1puppel1h1eradala
Now you will want to make a directory called h1eradala in the puppet directory. From there you can
put all of your hiera variables in a file called common.yaml.
Multiple Servers
One server is great, but if you have a real production infrastructure, it most likely doesnt consist of a
single machine. Vagrant is pretty nice in that it inherently supports it, you just need to do some
modifications to your Vagrantfile. If we wanted to have our database server be separate from our web
server. Here is our new Vagrantfile:
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
10 of 17 11/03/2013 10:25 PM
# -*- mode. ruby -*-
# v1. sel il=ruby .
varanl.coni1ure{"2"} do ]coni1]
# All varanl coni1ural1on 1s done here. The mosl common coni1ural1on
# opl1ons are documenled and commenled beloW. Ior a complele reierence,
# please see lhe onl1ne documenlal1on al varanlup.com.
# Every varanl v1rlual env1ronmenl requ1res a box lo bu1ld oii oi.
coni1.vm.box = "puppellabs-prec1se64"
coni1.vm.box_url = "hllp.11puppel-varanl-boxes.puppellabs.com1ubunlu-serv
coni1.vm.dei1ne .Web do ]WWW] # |1]
WWW.vm.hoslname = "dev-WWW.kloudless.vm"
WWW.vm.nelWork .pr1vale_nelWork, 1p. "192.168.33.10"
WWW.vm.nelWork .iorWarded_porl, uesl. 80, hosl. 8080
end
coni1.vm.dei1ne .db do ]db] # |2]
db.vm.hoslname = "db.kloudless.vm"
db.vm.nelWork .pr1vale_nelWork, 1p. "192.168.33.11"
end
# v1rlualBox Spec1i1c Cuslom1zal1on
coni1.vm.prov1der .v1rlualbox do ]vb]
# use vBoxManae lo cuslom1ze lhe vM. Ior example lo chane memory.
vb.cuslom1ze |"mod1iyvm", .1d, "--memory", "512"]
end
# v1eW lhe documenlal1on ior lhe prov1der you`re us1n ior more
# 1niormal1on on ava1lable opl1ons.
# Enable shell prov1s1on1n lo boolslrap puppel
coni1.vm.prov1s1on .shell, .palh => "boolslrap.sh"
# Enable prov1s1on1n W1lh Puppel sland alone.
coni1.vm.prov1s1on .puppel do ]puppel]
puppel.man1iesls_palh = "puppel1man1iesls"
puppel.man1iesl_i1le = "s1le.pp"
puppel.module_palh = "puppel1modules"
puppel.opl1ons = "--verbose --debu"
end
end
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
11 of 17 11/03/2013 10:25 PM
The primary change are the blocks labelled [1] and [2], those are just adding the host specific
configurations for the network settings, so that they can be dealt with separately and talk to each other.
Now that there are two boxes vagrant can refer to, for example if you wanted to just bring up the
webserver you would do vagrant up web. The name you refer it to is the key that is the argument to
coni1.vm.dei1ne.
In order to have puppet provision both of the servers, we also need to modify the site.pp file so we take
into account the fact that we have two nodes. This is pretty straightforward and ends up essentially
splitting the single node declaration into two, resulting in:
node `dev-WWW.kloudless.vm` {
# Coni1ur1n apache
1nclude apache
1nclude apache..mod..php
apache..vhosl { $..iqdn.
porl => `80`,
docrool => `1var1WWW1lesl`,
requ1re => I1le|`1var1WWW1lesl`],
)
# Sell1n up lhe documenl rool
i1le { |`1var1WWW`, `1var1WWW1lesl`] .
ensure => d1reclory,
)
i1le { `1var1WWW1lesl11ndex.php` .
conlenl => `>?php echo \`>p<Rello World!>1p<\` ?<`,
)
# "Real1ze" lhe i1reWall rule
I1reWall <] ]>
)
node `db.kloudless.vm` {
class { `mysql..server`.
coni1_hash => { `rool_passWord` => `herpderpderp` ),
)
1nclude mysql..php
# "Real1ze" lhe i1reWall rule
I1reWall <] ]>
)
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
12 of 17 11/03/2013 10:25 PM
Essentially all that happened, is that we split the original node definitions into two separate ones. Once
you have these manifests in place, running vagrant up brings up both virtual machines in sequence.
Once they are up, they can communicate over the private network via the configured ip addresses. The
hostnames you configure cant get resolved (it wouldnt be too hard to put the ips and hostnames in
each servers 1elc1hosls file through puppet, but that isnt too relevant here). Now this is more like
something you would see in your actual infrastructure.
Moving to the Cloud
Once you have a real application developed and configured you probably want it to be accessible to
everyone, so why not push it out to Amazons EC2! This can be done easily through the AWS provider
add on to Vagrant. This will basically be a different Vagrantfile that you will use specifically to push to
EC2. In order to replicate the configuration we had locally, you first need to install the plugin:
$ varanl plu1n 1nslall varanl-aWs
Once you have the plugin installed, we are going to take advice from the plugins docs to get started
quickly using a dummy box. All this means is that our configuration will be explicit within the
declaration of the box. To register the dummy box, we do the following:
$ varanl box add dummy hllps.111lhub.com1m1lchellh1varanl-aWs1raW1masler1d
Then we need to modify our existing Vagrantfile to create and provision the box, since it is going to be
pretty different, we can create the different configuration blocks:
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
13 of 17 11/03/2013 10:25 PM
# Be1n lhe AWS Prov1der Coni1ural1on.
coni1.vm.prov1der .aWs do ]aWs,overr1de]
aWs.access_key_1d = "Y0uR KEY"
aWs.secrel_access_key = "Y0uR SECRET KEY"
aWs.keypa1r_name = "KEYPATR NAME"
aWs.re1on = "us-Wesl-2"
aWs.am1 = "am1-ii68i8ci" # ubunlu 12.04LTS 1n us-Wesl-2"
overr1de.ssh.username = "ubunlu"
overr1de.ssh.pr1vale_key_palh = "PATR T0 Y0uR PRTvATE KEY"
end
# Th1s box W1ll be brouhl up 1n EC2
coni1.vm.dei1ne .Web_aWs do ]Web]
Web.vm.box = "dummy"
Web.vm.hoslname = "WWW.kloudless.aWs" # 0ummy hoslname
end
These blocks can just be added into your Vagrantfile before the final end. This assumes that you already
have an account and a key-pair set up, so you will need to substitute your credentials into the proper
place. I have chosen the Ubuntu 12.04LTS AMI because it is easy to use and us-west-2 because it is
pretty close to where I am located (it is in Oregon). Now here is the somewhat tricky bit, because of the
way that EC2 works, you wont really know the hostname of the machine before you bring it up and the
network configuration options of Vagrant dont support setting the hostname. There are a couple ways
around this:
Nodeless Puppet (https://github.com/jordansissel/puppet-examples/tree/master/nodeless-
puppet/): A pretty novel approach that is fact driven. It is interesting and probably what I
would recommend if you are going to use this in a real production environment.
1.
Just bring it up and do provisioning afterwards: This is clunky, but easy and what I will do for
this blog post.
2.
So you will bring up your vm with varanl up Web_aWs. The shell provisioning will go ahead just
fine, but the puppet provisioning will fail. Ths is ok, we just need another puppet node definition.
Basically I am going to just copy the node definition on dev-www (if you wanted to bring up the
database server in EC2 it would be the same kind of process):
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
14 of 17 11/03/2013 10:25 PM
node `TRE NEW R0STNAME` {
# Coni1ur1n apache
1nclude apache
1nclude apache..mod..php
apache..vhosl { $..iqdn.
porl => `80`,
docrool => `1var1WWW1lesl`,
requ1re => I1le|`1var1WWW1lesl`],
)
# Sell1n up lhe documenl rool
i1le { |`1var1WWW`, `1var1WWW1lesl`] .
ensure => d1reclory,
)
i1le { `1var1WWW1lesl11ndex.php` .
conlenl => `>?php echo \`>p<Rello World!>1p<\` ?<`,
)
# "Real1ze" lhe i1reWall rule
I1reWall <] ]>
)
You can replace TRE NEW R0STNAME with the short domain name that the node thinks it has, in my
case it was 1p-10-251-32-195. Now you can actually provision your vm with vagrant provision
web_aws. In order to actually view the test page, you will need to have your security groups set up
properly, but if you just want to check you can varanl ssh Web_aWs and then curl
hllp.11localhosl {hllp.11localhosl} and see that it works.
Extra Notes
Some things work differently when you are using the AWS provider and the main one you will notice is
the shared directories. These get syncd with rsync every time you run vagrant up, vagrant reload, or
vagrant provision. You can also build a bunch more aws configuration into your box definition, so you
dont have to specify it by hand.
Since it is in EC2 you can take advantage of tags and user data. In our production puppet environment,
we have an enc that decides what classes to give an instance based on its tags, but that requires a puppet
master, which I didnt really talk about (right now, vagrant just uses puppet apply).
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
15 of 17 11/03/2013 10:25 PM
Conclusion
Hopefully I have given you a good taste of how easy it is to put these two tools together to make your
development and deployment a lot easier! Puppet is a really great tool and I highly recommend learning
more so you can take full advantage of this work flow. I am still working to fully utilize all these great
tools and it would be great to hear about other peoples experiences.
16 thoughts on Automating Development Environments
with vagrant and Puppet"
One would add hostnames/IP addresses to /etc/hosts, not resolv.conf.
Oh lol, yeah good catch. Fixed.
1.
Well written introduction.
One thing to add. Ive done a similar Puppet preinstall script ( https://gist.github.com/dol/5776169
). The difference is that the script allows to specify a certain version to be installed. Even if
Puppetlabs ships a new version and removes some deprecated stuff, your Puppet code will work as
expected.
That is pretty nice, I explicitly didnt want to worry about versions for the sake of simplicity and
because I have been trying to keep my manifests up to date. I always get the feeling that it would
be pretty easy to get comfy in a version and that makes it hard to get out
2.
Nice article. Im slightly confused about why youve added a bootstrap to add Puppet. Isnt Puppet
added by Vagrant automagically?
I added a bootstrap script because the versions of puppet that are usually installed on vagrant
boxes tend to be out of date, so I opted to use a clean box and do some extra bootstrapping on my
own to make it more consistent with what I use on my production servers. I also added an
explanation in the bootstrapping section to avoid further confusion
Thanks, I thought as much but wanted to confirm.
3.
Howdy! This post couldnt be written any better! Reading through this post reminds me of my
previous room mate! He always kept talking about this. I will forward this write-up to him. Pretty
sure he will have a good read. Thank you for sharing!
4.
Pingback: vagrant puppet runliferun 5.
Pingback: Links for June 22nd through July 8th 6.
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
16 of 17 11/03/2013 10:25 PM
Pingback: Bookmarks for July 1st | Chriss Digital Detritus 7.
Pingback: Lamp server A perfect choice for your web host | Hosting Home 8.
Great post, detailed and well written. One small remark, the apache module uses mom_module =>
worker as default; to override it I had to use:
class { apache:
mpm_module => prefork,
}
in site.pp
Nice catch, that will probably come in handy for people who use non-threadsafe libraries.
9.
The bootstrap.sh file threw errors out to me. So I modified it like this to work for me:
wget -q https://apt.puppetlabs.com/puppetlabs-release-precise.deb -O /tmp/puppetlabs-release-
precise.deb
10.
Absolutely awesome! Many thanks for doing this. 11.
Follow
Follow The Kloudless Blog | Thoughts on the company, technology,
design, and the future of cloud"
Powered by WordPress.com
Automating Development Environments with Vagrant and... http://blog.kloudless.com/2013/07/01/automating-develo...
17 of 17 11/03/2013 10:25 PM

Das könnte Ihnen auch gefallen