Entity view (Content)

Boxen: How I stopped worrying about setting up my machine

By cali
Oct. 24, 2014

I joined Appnovation a few weeks ago, and was presented a brand new machine to get started with development training. The whole task of setting it up seemed like a daunting task. A developer's day is usually spent playing with the LAMP stack and good developers want to spend more time solving problems than prepping for it.

In recent years, the web development and devops communities have risen to the challenge of making web development less of a machine setup nightmare. I have had the opportunity of playing with Vagrant environment setup and absolutely loved its simplicity in spinning local development environments within minutes so I could get cracking on the problem at hand. However, the concept of a machine wide setup for preparing your machine for development instead of various environments running in it had never occurred to me before meeting Antoine and Jean Michel at the Montreal office. Despite its initial learning curve, the sheer flexibility of the technology has not only made my life easier but also compelled me to learn more about it. Boxen could eventually end up becoming part of the workflow of Appnovation, handing out pre-configured machines to new employees. Before, we can delve into my typical usage summary of boxen, lets get to know Boxen a little bit.

What is Boxen?

Boxen is a framework. It basically uses Puppet to automate your Mac provisioning. (Yes, sorry Linux guys). The benefits are many, ranging from user friendliness for a developer to immediate fixes for issues. Imagine, a new vulnerability has been reported overnight. In a flurry of e-mails, everyone seems to be trying to get the word across for suitable patches, and pushing fixes. In the Boxen world, it is as simple as disabling a particular feature. Developers can than pull those changes from the Boxen repo and everyone is synchronized. The project repo can be accessed here. The magic spells are written using Puppet, - which is a configuration management tool.

Boxen Setup

We need to install XCode. (XCode Command Line Tools would work as well if you run into trouble setting up your Apple id - I did). 

Also, enable full disk encryption and upload your SSH keys to github.

After this dependency fulfillment, it is time to clone the repo which sits in gitlab. 

sudo mkdir -p /opt/boxen
sudo chown ${USER}:staff /opt/boxen
git clone git@gitlab.appno.net:intbox/001-boxen-int.git /opt/boxen/repo

It provides a template for us to be able to start. It comes preconfigured with modules needed for development i.e. homebrew, nginx, git, etc. You can add or remove modules according to your requirements. For default repo installation, go to the repo folder, 

cd /opt/boxen/repo and execute ./script/boxen

Sit back and relax while this process finishes. Once the installation is finished, add the following line to your .bash_profile, [ -f /opt/boxen/env.sh ] && source /opt/boxen/env.sh

Boxen Usage

Boxen is a very flexible framework and a full tour of its capabilities is beyond the scope of this blog entry. I would just like to provide you with a snapshot of limited set of features that I use. For us, to become comfy with boxen - a visual tour of its folders would help a new developer to quickly appreciate its simplicity. The boxen repo has the following folders,


In the repo folder, we are interested in the modules folder. This folder contains two sub-folders- people, projects. Boxen works with manifests which hold all the node definitions to setup the target machine by including the modules that you need.

Modules Folder

 If you dig further into people folder, you see the manifests folder which contains *.pp files. Copy a manifest and rename it to YOUR-NAME.pp. The pp files contains the person's (developer) configuration settings in the following format,

class people::your-name {

$home = "/Users/${::boxen_user}"

file { "${home}/.bash":
ensure => 'directory',
}

file { "${home}/.drush":
ensure => 'directory',
}

# Git config override
Git::Config::Global <| title == "core.excludesfile" |> {
value => "~/.bash/.gitignore"
}

# include projects::project-name

Here, your-name can be replaced by your name.  While ensuring existence of the files containing key "ensure". The manifest also allows you to comment out a project you don`t plan on working on and just concentrate on grabbing the projects that you need. The uncommented include projects will be built.

Lets, check out the projects folder under modules and find the manifests folder. Open a project "pp" file. For illustrative purposes, we shall be using a Drupal 7 project file.

class projects::drupal7 {

  $project_name = 'drupal7'
  $php_version = 'php53'
  $core = 'drupal7'
  $docroot = 'docroot'

  boxen::project { "${project_name}":
    source        => 'https://github.com/vermuz/drupal7-sandbox.git',
    dir           => "${boxen::config::srcdir}/${project_name}",
    nginx         => 'projects/shared/nginx.generic-drupal.conf.erb',
    mysql         => true,
  }

  # local settings
  file { "${project_name}-sites-dot-dev":
    path    => "${boxen::config::srcdir}/${project_name}/${docroot}/sites/${project_name}.dev",
    ensure  => 'directory',
    require => Boxen::Project[$project_name]
  }
  file { "${project_name}-settings-php":
    path    =>"${boxen::config::srcdir}/${project_name}/${docroot}/sites/${project_name}.dev/settings.php",
    ensure  => 'present',
    content => template("projects/shared/d7/settings.php.erb"),
    require => File["${project_name}-sites-dot-dev"]
  }
  file { "${project_name}-drush-aliases":
    path    => "/Users/${::boxen_user}/.drush/${project_name}.aliases.drushrc.php",
    ensure  => 'present',
    content => template("projects/shared/d7/d7.aliases.drushrc.php.erb"),
  }
  file { "${project_name}-info-php":
    path    =>"${boxen::config::srcdir}/${project_name}/${docroot}/info.php",
    ensure  => 'present',
    source  => 'puppet:///modules/projects/utils/info.php',
    require => Boxen::Project[$project_name]
  }
}

The values are pretty self explanatory. Providing the project with a source-url, target directory and path to nginx recipe. This will create a "project-name.dev" folder in your docroot. It will also place a settings.php file in your development folder based on the Drupal 7 recipe coming from projects/shared/d7/settings.php.erb. It also creates an alias file for you under .drush in your home directory. The template being used is under projects/templates/shared/d7 where you can check the docroot setting as well as the uri and site path setting.

$aliases['local'] = array(
  'root' =--> '/Users/<%= scope.lookupvar "::boxen_user" %>/src/drupal7/docroot',
  'uri' => 'http://drupal7.dev',
  'site' => 'drupal7.dev',
  'target-command-specific' => array(
    'sql-sync' => array(
      'enable' => array('devel', 'views_ui'),
    ),
  ),
)

Once in your development environment, you can use - "drush use @drupal7.local" and "drush status" will provide you will all the information about your project. If you want to dig your claws deeper into the magic of boxen, have a look at the templates i.e. the nginx template where you can find information about logging and sockets,

nginx

The manifest also places an info.php file into your project folder. This info.php will help you check the status of various services in your environment.

That's it, type boxen in your shell. It will setup your environment. It will create project folder in your home directory, under src folder based on configuration specified in "boxen:config:srcdir". You are good to go from there. In our case, the url would be - drupal7.dev.

Note: If you cannot see your site. Try accessing, drupal7.dev/info.php for more information. 

Cool Feature : PHP Version Hopping

Did you know? you could hop among different php versions according to your requirements. 

$ php-version 5.3
$ php-version
* 5.3.29
  5.4.33
  5.5.17
$ php --version
PHP 5.3.29 (cli) (built: Sep 29 2014 16:23:04)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies
    with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans

If you have to change something in the php.ini file, the file in our case (depending on the version of php you choose) is located in, /opt/boxen/homebrew/etc/php/5.3/php.ini. Apply your change, and don`t forget to restart php-fm. How would you do that in a Mac?

$ launchctl unload -w /Library/LaunchAgents/homebrew.mxcl.php53.plist
$ launchctl load -w /Library/LaunchAgents/homebrew.mxcl.php53.plist

* Php.ini changes could be because of certain project related permissions or limit values. Sockets can be seen in, boxen/data/project-sockets/.

Feel Brave? Want to add more Boxen modules?

You can add modules to the PuppetFile in your boxen repo, in the following fashion,

github "hub",        "1.0.0"
github "inifile",    "0.9.0", :repo => "cprice404/puppetlabs-inifile"
github "nginx",      "1.4.0"
github "java",     "1.1.0"

The bottom line includes the Java module from Github using the tag "1.1.0" from the github repository "boxen/puppet-java". Now, Puppet knows where to download the module from when you include it in your SITE.pp or PERSON.pp

This blog entry is not a comprehensive study of boxen and its capabilities - rather the intention is to give the reader a glimpse into the daily usage of a typical developer and how much flexibility it offers to its users. Of course, this is just the start of this workflow usage. Boxen should be a group effort - every developer who starts working on a project that has no previous manifests should add his or her own manifests to the repo so that the other developers do not have to spend time configuring it. Once, the manifest is in the repo. All it takes is a "boxen" command to spin your environment and start work on your task.

 

Post Tags: