One of the things that initially attracted me to PHP was that I could write all of my apps in pure PHP, and they would run anywhere I deployed them.
I was young and dumb back then, and I've learned a lot in the meantime. One of the things that I've learned is that your environment is incredibly important. A misconfigured setting is probably the biggest reason that code deployments fail. It's so important that it's almost universally recognized that if your code has any complexity, you need a staging server to test your code in a production-like configuration before you push out your releases.
There are a plethora of tools available to help you manage these jumps from development to staging to production. There are all sorts of problems to deal with when doing this, from preventing the execution of partially-uploaded files, to ensuring that all of the files inside a user request are from the same revision, to managing your load balancer configuration as nodes go down for updates. There are also all sorts of software packages to help you deal with this, ranging from simple shell scripts to rsync your code, to post-commit hooks, to complex, environment-specific homebrewed systems.
What is examined less oftena-aand in much less detaila-ais how to manage configuration files. At first glance, maintaining configurations on a cluster of nodes seems easy. They're all the same, right? Yes, that is true until you start to notice that they need slightly different hosts files, or have slightly different roles. Your perfect world, where you just rsync a single directory to all of your hosts, quickly starts to fall apart. Pretty soon, you start writing Bash scripts to do different things to different types of nodes, and it all gets complicated. Of course, there are other software packages to help you with this problem, too. For example, Puppet is excellent at configuration management, and you can truly manage a massive installation of machines very easily with it. However, you really only have a handful of machines right now, you're going live with the beta tomorrow, and you don't have the time or the energy left to learn an advanced configuration management system. Plus, maybe you're just a really good PHP developer, and don't know much else about Unix-like systems. That's nothing to be ashamed of.
Luckily, there's a convenient file archive management system in front of you right now. You've been using it for a while, and it lets you do all sorts of cool stuff. You can use it to just copy files, to run bash scripts before or after installation, and to keep track of which versions you need of all of your assets. It's a system that you're familiar with that lets you tell your servers that you need Apache 2.2, PHP 5.3, MySQL 5.1, the current release of Postfix, and even custom modules.
This system is your Linux distribution's package manager. What, you thought you were the first person to have these problems? Package managers keep you safe every time you upgrade Apache, and they can keep your web app safe, too! In this example, I am going to use a Debian-based system, because I love Aptitude. However, most every distribution has a tool with similar capabilities, and a little Google research will yield quick rewards. So, let's dig in.
In our example, we've thought about what we need need managed, and we've come to the conclusion that we need the following on every node in the cluster:
- Customized Apache, MySQL, and PHP configuration files
- A default document root directory which contains a small check script for the load balancer to poll
- A hosts file entry for our four load-balanced MySQL servers
- A firewall (iptables script)
- An SSH configuration
To begin with, let's create a directory named after our package file, l33tbox. This directory represents what we want to copy to every system, relative to root. In this directory, we also need a subdirectory called DEBIAN, which will contain all the package control files.
At this point, our directory structure is pretty bare:panda@pandastation:~/phpadvent$ find . -type d . ./l33tbox ./l33tbox/DEBIAN panda@pandastation:~/phpadvent$
The next thing we need to do is build a control file for our package. This will be be located at l33tbox/DEBIAN/control with the following contents:Package: l33tbox Version: 0.1 Section: main Priority: standard Architecture: all Depends: vim, apache2-mpm
Truncated by Planet PHP, read more at the original (another 6486 bytes)