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.
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
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.
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.
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?
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!
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.