Provisioning Phalcon (and other tools) with Vagrant

Matthew Setter's last article on PuPHPet covered the easy GUI-backed creation of Vagrant VMs. PuPHPet is an absolutely awesome tool in getting up and running with a development environment really fast, and offers some very neat default options.

But what if we want to step outside the defaults? What if we'd, for example, like to install a PHP extension that isn't part of the default distribution and doesn't exist in package managers?

In this tutorial, we'll make sure the Phalcon framework is installed by default when we run vagrant up. Pre-installing software on a Vagrant VM is called provisioning.

Getting ready

Please walk through Matthew's article before moving along with this one. Simply make sure you download a ready PHP-enabled VM.

In this particular case I used PHP 5.4 with Ubuntu (5.5 won't work with it just yet via PuPHPet), but if you've got your own configuration you're used to, please feel free to use it – just make sure you can get to a good phpinfo screen before continuing. Make certain your PHP configuration works and you can access the VM through the browser and execute a PHP script like

<?php
phpinfo();

Ideally, your browser should display something like this:

The basics of Provisioning

Vagrant offers several ways to provision software into your Virtual Machines. There's Puppet (what PuPHPet is based on), Chef, Docker, and more. What we'll be using is pure good old shell commands – Vagrant can execute a shell file we write if we pass it to its provisioning settings.

So, let's say you need to install the text editor joe and want to do it through shell. In your PuPHPet folder's shell subfolder, you would create a joe.sh file with the following contents:

#!/bin/bash
sudo su
apt-get install joe

This shell script first identifies itself as executable by bash (optional), requests superuser permissions, and then it installs joe through the regular channels. To actually have this executed, we modify the Vagrantfile in the PuPHPet folder by adding the line

config.vm.provision :shell, :path => "shell/joe.sh"

under the last config.vm.provision... line/block. Now if we run vagrant up in our PuPHPet folder, our VM will have joe installed as soon as it boots.

Installing Phalcon

As per Phalcon's online installation instructions, the compilation process is straightforward:

git clone git://github.com/phalcon/cphalcon.git
cd cphalcon/build
sudo ./install

However, we also need to enter phalcon.so into the PHP configuration, restart the server, and make sure all the prerequisites are installed (they are, PuPHPet took care of that for us). Let's do this step by step.

In the shell subfolder again, create the file install_phalcon.sh. Give it the following content:

#!/bin/bash
sudo su
git clone git://github.com/phalcon/cphalcon.git
cd cphalcon/build
./install
cd ..
cd ..
rm -rf cphalcon

Now if you re-run vagrant up after running vagrant destroy, you can see the phalcon.so extension in the PHP extensions folder:

However, in order for it to actually be used, phalcon.so needs to be added to the PHP configuration. After adding it, we also need to reload the server in order to load the new configuration. Improve the shell file above by adding the following statements to the bottom:

echo 'extension=phalcon.so' > /etc/php5/mods-available/phalcon.ini
ln -s /etc/php5/mods-available/phalcon.ini /etc/php5/cli/conf.d/phalcon.ini
ln -s /etc/php5/mods-available/phalcon.ini /etc/php5/apache/conf.d/phalcon.ini
ln -s /etc/php5/mods-available/phalcon.ini /etc/php5/fpm/conf.d/phalcon.ini

service apache2 restart

First, we create a phalcon.ini file in the /etc/php5/mods-available directory. We could echo it directly into php.ini, but this is just cleaner. Then, we symlink that newly created file to all the locations from where PHP can be run: Apache, command line and FPM. That way, all our potential PHP runtimes have Phalcon available. Finally, we restart Apache.

If you try running vagrant up now (after running vagrant destroy), you'll notice the phpinfo screen displaying Phalcon as loaded after you re-visit the VM's IP in your browser.

But what if the server process is named differently? For example, if it's "httpd", or just "apache", and not "apache2"? Furthermore, what if we've got a different distro? On CentOS phalcon.ini should go to /etc/php.d/, and on other distros into other locations. Finally, what if we only do a vagrant halt and then run vagrant up but force a re-provision with the --provision flag? Wouldn't it be better to simply ignore the Phalcon installation if it's already installed?

Luckily, slogsdon took all this into account for us. He built an excellent Phalcon installation shell script, ripe with IF clauses and more, and even created a phalcon-tools installation script.

To install Phalcon with all the above taken into account, place install_phalcon.sh into the shell folder of your PuPHPet download, and add it to the provisioner like we did for joe before. If you'd like to install Phalcon tools, do the same with install_phalcon-devtools.sh. That's all you need to do – the script accounts for different servers and setups so all you need to do is have it run.

Now you too can have an out-of-the-box ready Phalcon installation ready for development at the snap of your fingers. Naturally, you'll need to do some additional tweaks to get URL rewriting to work on Nginx (just follow the Phalcon docs), but once the extension is installed and loaded by PHP, the hard part is over. What's best, you can use this approach to install Phalcon on any of the PuPHPet supported environments as well – Digital Ocean, Rackspace or AWS. Just plug slogsdon's shell into the provision settings, and you're ready to go!

Conclusion

In this tutorial, we covered the basics of provisioning via shell and installed Phalcon (and joe) with a booting VM. Coming soon is a followup article from Matthew Setter which will deal with further customizations of the downloaded provision settings from PuPHPet.

To get familiar with the full workflow of Vagrant and Puppet, please do keep following this series as it's about to get a whole lot more interesting!

If you have any comments, uncertainties, problems or just general feedback, please leave it in the comments below and I'll do my best to address it as soon as possible! If you've got your own setup you'd like to share with the rest of us, do get in touch with me via +BrunoSkvorc and we'll talk.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Chris Emerson

    “But what if the server process is named differently? For example, if
    it’s “httpd”, or just “apache”, and not “apache2″? Furthermore, what if
    we’ve got a different distro? On CentOS phalcon.ini should go to /etc/php.d/, and on other distros into other locations. Finally, what if we only do a vagrant halt and then run vagrant up but force a re-provision with the –provision flag? Wouldn’t it be better to simply ignore the Phalcon installation if it’s already installed?”

    Surely this exactly the type of stuff Puppet handles without a problem? Why use a shell script when Puppet can do all of this without any of these concerns?

    • http://www.bitfalls.com/ Bruno Skvorc

      You’re right, and thanks for the feedback. Honestly, I’m just getting to know Puppet and couldn’t figure out how to replicate this procedure in it in the 24 hours or so I’ve dedicated to it. If you have a way, I’d love to include it in the article and credit you, but I assume it involves some sort of difficulty since the author of the script didn’t resort to it either. I definitely planned to update the article with a Puppet version later on once I got a firm grasp on it.

  • duythien

    cool

  • http://www.matthewsetter.com/ Matthew Setter

    Hey Bruno, thanks for the plug, and the reference to Phalcon. I’ve been a long time Zend user, but Phalcon looks really interesting, especially as I can now bootstrap it very quickly.

  • Mufleeh Sadique

    It seems like vagrant provision will do all rather than vagrant up after vagrant destroy. Is that correct?

    • http://www.bitfalls.com/ Bruno Skvorc

      Vagrant provision will do just the provisions. Vagrant up will do booting AND provisions, IF destroy was called. If HALT or SUSPEND was called, then vagrant up only does booting.

      • Mufleeh Sadique

        Well that makes sense, in this case is booting necessary or provision is good enough?

        • http://www.bitfalls.com/ Bruno Skvorc

          You run Vagrant Up if your VM isn’t running. You run vagrant provision if it is running, but you want to re-run the provisioners. Vagrant Up always runs Vagrant Provision IF provisioning hasn’t been done before, and IF the VM wasn’t destroyed before running Vagrant Up.