In previous post i scratched the topic of managing and sharing your development environment. By using Vagrant to manage virtual machines and one of provision tools you can setup configurable environment. Furthermore you can setup your production machine to match this configuration. Lets roll up our sleeves and set it up.
Vagrant setup
You need to install few things: Vagrant, VM manager (i’ll choose VirtualBox) and ruby. Also as a base linux distribution i’ll use Ubuntu.
First step is to prepare Vagrant configuration so execute vagrant init
command. This will generate sample Vagrantfile
with lots of helpfull comments, for now you can delete them to keep configuration clean and tidy. As a box name use ubuntu/trusty64
.
Now each time when you execute vagrant up
vagrant will search for box with this name. If doesn’t find it in imported boxes will search his online catalog and download it for you. You can also safely vagrant destroy
if needed (for sure we will use it later).
Provisioning
Vagrant has built in functionality to provision box while creating it. What it means is that you can execute custom scripts that will install and configure software for you. There are some tools that support this kind of operations which i mentioned in previous post. For now i will use chef solo provisioner.
In short Chef provisioning uses sets of instructions (called recipes) to setup virtual machine. Recipes can be configured with attributes use templates and be separated in several files. All of those can be combined into Cookbook. There are many configured cookbooks and can be found on Supermarket. Some of them are fine tuned and can be found on [GitHub][github-site].
To easily use and manage existing cookbooks install librarian-chef ruby gem gem install librarian-chef
and initialize it librarian-chef init
in folder with Vagrantfile
. Chef configuration file Cheffile
will contain commented out examples delete them to keep it clean and tidy.
You can group and tune cookbooks into roles. Most often they are grouped into functional groups, for example if your environment is split into 2 VMs (database server and application server) you will end up with 2 roles: database and application. Let’s create one role to keep Chef configuration out of Vagrantfile
.
Create folder roles
and inside of it ruby script base.rb
. Role scripts needs to have name so add name 'base'
. We will add more to it when we add some cookbooks.
Now we need to tell Vagrant where is should search for cookbooks and roles. Also add this role to actual vagrant box.
Cooking ruby
Now lets add first cookbook to install RVM and configure it to install newest ruby version (2.2.0). Add cookbook 'rvm', '~> 0.9.2'
to Cheffile
and execute librarian-chef install
. Cookbook for rvm and all it’s dependencies will be places in cookbooks
folder which will be searched by Vagrant provisioning.
Next step is to adjust base
role to install rvm and ruby. To install rvm system-wide accordingly to README we need to add recipe[rvm::system]
recipe to run list.
Now lets adjust attributes to install ruby 2.2.0, use it as a default and gem bundler
. Also to give user vagrant
ability to install gems we need to add it to rvm
group.
Now lets execute vagrant reload
to refresh synchronized folders and vagrant provision
to make use of installed cookbooks and set role. It can take a few minutes to complete. When finished you can vagrant ssh
into machine and check version ruby -v
and installation folder of ruby which ruby
.
Every time when you execute vagrant destroy
and vagrant up
you will end up with VM configure exactly same way.
Cooking postgresql
As a database backend PostgreSQL is used frequently if application is either self hosted on VPS or on Heroku. In second case PostgreSQL if forced by hosting provider. So having it configured in development enviornment is helpful. Let’s add required cookbook and adjust our role.
Don’t forget to execute librarian-chef install
to actually install new cookbook.
If we are using standalone version of chef (other option is that chef recipies are managed by dedicated server) there is a need to setup password for postgres
user. Another catch is that to allow postgres
user to be authenticated by password. That is why we set pg_hba
variables which are reflected in configuration with same name. I took value of this attribute from original recipe and changed authentication method from ident
to md5
for postgres
user.
Last touches
Last things to setup in vagrant is to expose port that is used by rails to host machine. Current folder is mounted in /vagrant
path by default. If project is kept in different folder than folder with Vagrantfile you need to explicit setup it to be mounted in VM. Let’s do this and we will be able to create new project!
All you need now is to vagrant up
then vagrant ssh
and cd /path/to/project/in/vm
to be in your development sandbox. Your default machine won’t be cluttered with many per project configurations. You can easily experiment with different setups and event split your application into many dedicated servers. Most important it is OS agnostic, easily replicable, configuration consistent and can be shared with everyone.
Please be warned to keep password for production database safe and secure. This Chef configuration is written for development environment not production.