Creating a Vagrant Base Box with CentOS 6.5, Puppet and Virtual Box

Vagrant is a great tool for developers to use their favorite IDE, within their favorite OS, all while using their favorite VM.
Doing so lets you work in a development environment that is identical to where your application will be deployed.

Puppet is a popular provisioning tool used to duplicate the configuration of systems quickly. Automated system administration. 😀
This article will show how to create a Vagrant Base box with CentOS 6.5 (64-bit), install Puppet Agent and configure it to sync up to your Puppet Master.

Now if you’re thinking… Why would we want to do this when there are tons of base boxes already available?
There are and that’s true, however creating your own allows you to customize what you truly need and don’t need for your team, and also be certain on what’s really installed.

Note: This article assumes you’ve already installed CentOS 6.5 as a Virtual Box VM, the correct Guest Additions for your Virtual Box version, and are already running a Puppet Master.

This article will show you:

  • How to create a Vagrant CentOS 6.5 base box from an already installed CentOS 6.5 VM Image.
  • How to add your newly created base box to Vagrant in order to use it.
  • How to initially provision Vagrant to connect to your company’s Puppet Master.

First we need to install the right version of Vagrant for your OS distro.

Next, we need to boot up your already installed CentOS Virtual Box Virtual Machine.
VBox_f

Next, we’re going to install Puppet Agent on our freshly installed CentOS VM. Our goal (when we do our initial Vagrant provision) is to have Puppet Agent already installed on our base box. This way, we can use Puppet Agent to create our Vagrant environment according to what our dev team’s configuration “node(s) profile” on the Puppet Master is. Puppet Agent will sync up with our Puppet Master to tell us which packages and configurations are needed to install for the Vagrant environment.

Note: Configuring Puppet Master is beyond the scope of this article, but there are many tutorials out there to help.

OK, with our VM in Virtual Box running, login and install Puppet Agent.
Vagrant-login_f

Install Puppet Agent


# sudo yum install puppet

Next, we want to be able to use Puppet’s “file_line” function. We’re doing this in order to modify Puppet Agent’s config file with our Puppet Master server location.
We could of manually edited it on the VM before creating our Base Box, but this way gives much more flexibility. You could have more than one team, with each using different Puppet Masters that have different development configurations.

Note: Puppet’s “file_line” function is usually only used for minor file modifications. If you have config files that need to be modified according to a much more complex use case, then the tool you want to use is Augeas.

Install Puppet’s Stdlib module on the VM


# puppet module install puppetlabs-stdlib

Now that those are installed, make sure your VM has everything installed that you initially want (puppet agent, initial packages, hostname, specific dev user/group/permissions, etc), then it’s time to create a Vagrant Base Box from our VM. Don’t worry if you’ve forgot something, you can always go back to the original VM and modify it. Meaning, this won’t modify your VM, it just creates a copy.

Now shutdown your VM. On your host OS we’re going to create the base box.

Create a Vagrant Base Box from your CentOS Virtual Box VM


// --output: the name your base box will be
// --base: your CentOS VM name
# vagrant package --output CentOS-6.5-x86_64_puppet.box --base CentOS-6.5-x86_64

This creates a Vagrant base box file in Vagrant’s box directory named CentOS-6.5-x86_64_puppet.box

Next we need to add this base box to Vagrant so we can use it.

Add the Base Box to Vagrant


# vagrant box add CentOS-6.5-x86_64_puppet CentOS-6.5-x86_64_puppet.box

We can view our base boxes by asking Vagrant.

List the current base boxes


# vagrant box list

vagrant-list-base-boxes_f

Note: I’m storing my base boxes in a custom directory I created just for them that’s off of my SSD drive (since many base boxes can potentially take up a lot of room). Initially Vagrant stores them on the main drive. This can be changed by modifying the default path in your env variables.

Now it’s time to actually *use* Vagrant. 🙂

Create a project directory called “testvagrant” on your host machine and cd to it.

Create and cd to the “testvagrant” directory


# mkdir testvagrant
# cd testvagrant

Next, we’re going to initialize a vagrant environment.

Create Vagrant Env


# vagrant init

This will create a Vagrantfile in the “testvagrant” directory. We’re going to edit this file to setup Vagrant and do our provisioning with Puppet.

Inside our “testvagrant” directory we’re going to create Puppet’s standardized directory tree structure.

Note: This isn’t necessary, it’s just good habit. 🙂

Create the directories


testvagrant
-- puppet
 -- manifests
  -- site.pp
 -- modules
  -- init
   -- manifests
    -- init.pp

Now we want to edit init.pp and add

Add to init.pp


class init {
    # config Puppet Agent (preinstalled on BaseBox)
    # Chaining Arrows (ordering) to prevent race conditions
    file { '/etc/puppet/puppet.conf':
        ensure => 'present',
    } ->
    # server is the location of the Puppet Master domain
    file_line { 'Configure Agent - puppetmaster server':
        path   => '/etc/puppet/puppet.conf',
        ensure => 'present',
        line   => '    server = puppet.ltdev',        
    } ->
    file_line { 'Configure Agent - report':
        path   => '/etc/puppet/puppet.conf',
        ensure => 'present',
        line   => '    report = true',        
    } ->
    file_line { 'Configure Agent - plugin sync':
        path   => '/etc/puppet/puppet.conf',
        ensure => 'present',
        line   => '    pluginsync = true',        
    }
}

Note: Rememeber, if you have a config use case that’s complicated, use Augeas.

Now we want to edit site.pp and add

Add to site.pp


node default {
    include init
}

Now that our Puppet Agent config files are ready to be modified we need to setup Vagrant and tell it how to provision. We do this by editing our Vagrantfile.

Edit Vagrantfile configuration


# This is the name of your base box
config.vm.box = "CentOS-6.5-x86_64_puppet"

# Our VM will be running our web server on port 80 but forwarding to our host OS on port 8080
config.vm.network "forwarded_port", guest: 80, host: 8080

# This is the directory that will be in sync on your host with your guest (VM) default is 
# /vagrant which is the root directory for that vagrant init (where your Vagrantfile is located)
# Note: I am using Samba for performance reasons with Symfony 2, however try the default 
# sync first.
config.vm.synced_folder ".", "/vagrant", type: "smb"

# Provision with Puppet
config.vm.provision "puppet" do |puppet|
    puppet.manifests_path = "puppet/manifests"
    puppet.manifest_file  = "site.pp"
    puppet.module_path = "puppet/modules"
end

Now its time to fire Vagrant up and provision! *cough* If everything went correctly.. 🙂

Start Vagrant


# cd testvagrant
# vagrant up

vagrant-up_provision_f1

And this is the modification Puppet did by using “file_line” to our /etc/puppet/puppet.conf

puppet-conf_f

Note: Vagrant only provisions on the first “vagrant up”, however you can force it to provision again if you need to by

Force Vagrant Provision


# vagrant up --provision

That’s it. If you need to you can reference how to use Vagrant here.
Have fun! 😀

Phusion Passenger on Apache 2.4: ‘undefined symbol: unixd_config’

If you or your company has come across this error while trying to start Apache 2.4 with Passenger, don’t worry there’s an easy fix. Your Passenger module is compiled for the wrong version of Apache, usually 2.2. Apache 2.4 has many changes and unixd_config has been renamed to ap_unixd_config in version 2.4. The fix is to recompile the Passenger module against your correct Apache version.


Verify your APXS2 Environment Variable location
First you need to make sure your APXS2 Environment Variable is pointing to the correct Apache version path.

Usually located at


cd /etc/sbin
ls | less

apxs_f

Verify the apxs location with what’s set as APXS2 in your environment variables.


env

If the path is not correct, update it (only will be for this shell)

Update for your shell session


export APXS2=/location/to/apxs



Next locate where your Apache 2.2 mod_passenger.so module is located.

Usually located at


/usr/lib/ruby/gems/1.x/gems/passenger-4.0.x/buildout/apache2/mod_passenger.so

You can also verify where Apache is loading it from by checking your PuppetMaster Vhost configuration file.

Usually located in Apache’s conf.d directory


vim /etc/httpd/conf.d/puppetmaster.conf

After you have located it, rename your Apache 2.2 mod_passenger.so module to something else. You don’t want it to get overwritten in case you still want to use Passenger with your old Apache version.

Rename Apache 2.2 mod_passenger.so


cd /usr/lib/ruby/gems/1.x/gems/passenger-4.0.x/buildout/apache2
mv ./mod_passenger.so ./mod_passenger_httpd22.so



Now all that’s left is recompiling mod_passenger.so against Apache.2.4.

Recompile Passenger


passenger-install-apache2-module

passenger-install_f

Now follow the directions for the recompile.

After the recompile, verify the LoadModule path is correct in your PuppetMaster.conf VHost config file.

If it is, just start Apache and you should be good to go.

Have fun! 🙂

Installing HHVM with Apache 2.4 on CentOS 6.5 (64 bit)

This is for those of you who love being on the bleeding edge of technology like me. This will be a brief introduction to installing Apache 2.4 and Facebook’s HHVM (Hip Hop Virtual Machine) in order to increase web application performance.

Apache 2.4 is the newest iteration of Apache’s web server with multiple performance improvements and Facebook’s HHVM is the new kid on the block that brings massive performance gains to PHP. HHVM achieves this by compiling PHP into bytecode, which is then translated into machine code by HHVM’s JIT (Just in Time) compiler. When using HHVM, this also gives the ability to use Facebook’s new statically typed language called HACK.

HHVM also works with most of PHP’s popular frameworks. If you work with popular enterprise level frameworks like Symfony 2, this can be an amazing asset.


First we need to prepare the install process by adding a few repositories for yum to use. Since CentOS 6.5 (as of the time of this post) doesn’t contain Apache 2.4 in their base or epel repositories, we need to look for another option. We could compile from source, however Remi Collet and Jan Kaluza from Red Hat have created a RHEL repo httpd24-epel that contains Apache 2.4 that is perfect for our needs. This repo installs Apache 2.4 in /opt. View why here.


For HHVM we have the same couple of options. We could either build it from source, or we can use Naresh Kumar’s wonderful repo called the Hop 5 Repo.

Using these repos is the best choice since we can manage our Apache 2.4 and HHVM installs with our package manager and not have to worry about future problems.


— PREPARATION —

Go to the repo directory

cd /etc/yum.repos.d

Add the Remi Repo

sudo wget http://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo

Add the Hop 5 Repo

sudo wget http://www.hop5.in/yum/el6/hop5.repo


— INSTALL PROCESS —

Install Apache 2.4

sudo yum install httpd24-httpd httpd24-httpd-devel httpd24-mod_ssl

This will place Apache 2.4 under /opt.
See why here

Install HHVM

sudo yum install hhvm

hhvm_install_f


— CONFIGURATION PROCESS —

Configure Apache
This article uses a VHost and assumes you already know how to setup one for Apache, however a Virtual Host is not necessary for HHVM.

Edit httpd.conf

cd /opt/rh/httpd24/root/etc/conf
vim httpd.conf

Ensure this line is not commented out

IncludeOptional conf.d/*.conf

Configure a Virtual Host for Apache

Go to the Apache 2.4 config directory

cd /opt/rh/httpd24/root/etc/conf.d

Create a Virtual Host config file as root (if non existent)

vim httpd24-vhosts.conf

Add the following lines

<VirtualHost *:80>
  ServerName hhvmtest.dev
  DocumentRoot /var/www/html/hhvmtest
  ErrorLog logs/hhvmtest.dev-error_log
  CustomLog logs/hhvmtest.dev-access_log common

  # where HHVM is running   # use either Proxy Pass or ProxyPassMatch   # ProxyPass routes all traffic to FastCGI   ProxyPass / fcgi://127.0.0.1:9000/var/www/html/hhvmtest   # ProxyPassMatch regular expression routes only PHP files   ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/hhvmtest/$1
  <Directory /var/www/html/hhvmtest> # relaxed permissions for testing     AllowOverride all     Options -MultiViews     Require all granted   <Directory> </VirtualHost>


— TESTING —

Start HHVM as a server in FastCGI mode in the background (run as root or sudo it)

/usr/bin/hhvm --mode server -vServer.Port=9000 -vServer.Type=fastcgi &

Verify HHVM is running and PID

ps aux | grep hhvm

hhvm-running

Start Apache

sudo service htttpd24-httpd start

Create Document Root

cd /opt/rh/httpd24/root/var/www/html
mkdir hhvmtest

Create index.php

cd /opt/rh/httpd24/root/var/www/html/hhvmtest
vim index.php

Add the following lines


 <?hh echo 'test ';
  $test = 2 + 2;
  echo  $test;
  echo phpinfo();

Create index.hh

vim index.hh

Add the following lines


 <?hh echo 'test ';
  $test = 2 + 2;
  echo  $test;
  echo phpinfo();


Now open your browser and go to

http://hhvmtest.dev/index.php

If everything goes correctly you should see the string

test 4 HipHop

Now open your browser and go to

http://hhvmtest.dev/index.hh

If everything goes correctly you should see the string

test 4 HipHop

When you output

phpinfo();

You should see the string 'HipHop'.

HHVM returns the string HipHop when you output phpinfo.



Also verify HHVM is working for php tags by changing in both index.php and index.hh

<?hh

to

<?php 


If you want to run HHVM on system boot. Either create an init bash script or just add the above HHVM line to rc.local

Go to rc.local

cd /etc/rc.local
vim rc.local

Add the following line to the bottom of rc.local

/usr/bin/hhvm --mode server -vServer.Port=9000 -vServer.Type=fastcgi &

That’s it enjoy! 😀