Update 8/27/2010: MacPorts disables all the default extensions when it compiles PHP, so I need to add back in the default POSIX extension.
Every time I reinstall one of my OS X systems there’s a learning curve where I try to figure out what exactly I’d had installed using MacPorts before I wiped it and the commands and variants I used to get there. Since I’ve now done this on both my systems in the last week it’s time to finally come up with an exact series of steps so I’ll have something to look at the next time around…
The Software Stack
I usually install Apache, PHP, MySQL, Subversion, and Git. Through dependencies we’ll get other tools that I consider essential: curl, rsync, sqlite, etc.
5.3 vs. 5.2
I recently switched from the legacy PHP 5.2 ports to the new 5.3 versions. If you’re still stuck at 5.2 for some reason you’ll want to install the php52 port with a number of variants. For the most part you should be able to substitute in the names of the separate 5.3 ports for the variants for 5.2, but double check the available variants to be sure.
php-cgi vs. mod_php
In my production environment I use Apache 2.2 with the Worker MPM, mod_fcgid, and php-cgi. I’ve run into some assorted problems (like mod_rewrite configurations) in the past when I’ve switched between mod_php in development and php-cgi in production, so I’m now trying to use the same configuration for both.
Install Order
I usually do everything in pieces just to make it easier for me to keep up with what I’ve installed and tackle any problems or errors I might run into. Strictly speaking I’m sure you could combine everything into one massive run, but the order I typically use is:
- Apache
- Base PHP
- mod_fcgid
- Configure and test these 3
- MySQL client and server
- Configure MySQL
- Assorted additional PHP extensions including php-mysql now that the server is installed.
- Final tools: Subversion, Git, anything else.
Apache
sudo port install apache2 +workermpm
PHP
sudo port install php5 +fastcgi
mod_fcgid
sudo port install mod_fcgid
Configure Apache, PHP, mod_fcgid
Now that our core web stack is installed we can make sure they’re all working together nicely.
Since we’re setting up our own mod_fcgid configuration, we’ll have to edit Apache’s config file manually. Open /opt/local/apache2/conf/httpd.conf in your favorite text editor.
Load mod_fcgid
Look for a huge mass of LoadModule lines. At the very end, add:
LoadModule fcgid_module modules/mod_fcgid.so
Change User and Group
Since it’s only a development box, I prefer to avoid a lot of permissions and ownership issues by simply running Apache as myself. Right below the modules, we’ll change the User and Group lines:
User chris Group staff
OS X puts users in the staff group by default, so you should only need to substitute in the name of your user account.
Document Root
Again, since it’s a development box I prefer just to serve pages out of my Sites directory, so next I’ll find these two lines:
DocumentRoot "/opt/local/apache2/htdocs" <Directory "/opt/local/apache2/htdocs">
And change them to:
DocumentRoot "/Users/chris/Sites" <Directory "/Users/chris/Sites">
AllowOverride
Next I need to change the directives that are allowed in .htaccess files so things like mod_rewrite rules will work. Inside the Directory block, find AllowOverride and change it to All:
AllowOverride All
Index Page
By default Apache will only serve up index.html pages when you request a directory. I prefer to use the .htm extension and need to allow PHP:
DirectoryIndex index.html index.htm index.php
mod_fcgid Configuration
Finally, we need to tell Apache to use mod_fcgid to execute any pages with a .php extension. At the very bottom of the file, add:
<IfModule mod_fcgid.c> AddHandler fcgid-script .php DefaultMaxClassProcessCount 4 DefaultInitEnv PHP_FCGI_MAX_REQUESTS 0 DefaultInitEnv PHP_FCGI_CHILDREN 0 FCGIWrapper /opt/local/bin/php-cgi .php <Files *.php> Options +ExecCGI </Files> </IfModule>
You can research mod_fcgid configurations and tweak the 3 numbers (4, 0, and 0) if you wish, but I’ve found these defaults reliable enough.
Test the Web Stack
Now that we’re done configuring we need to cycle the Apache server to make sure it’s running and using the latest configuration. MacPorts provides a convenient method to add and remove launchctl launch daemons. Make sure Apache is stopped:
sudo port unload apache2
And start it again:
sudo port load apache2
Create an info.php file in your Sites directory:
<?php phpinfo(); ?>
Now load up http://localhost/info.php and you should see PHP’s output. If not, well, start looking at your logs, you probably typo’d something…
MySQL Client and Server
Installing the MySQL client and server couldn’t be easier:
sudo port install mysql5 mysql5-server
Setup MySQL
Check the end of the port install output and it’ll tell you which command to run to setup MySQL:
sudo -u _mysql mysql_install_db5
After that, be sure to start up MySQL the same way we started Apache:
sudo port load mysql5
And the output of the install_db5 script should give you another one to run, which will walk you through steps for securing MySQL (most notably changing the root password):
sudo /opt/local/lib/mysql5/bin/mysql_secure_installation
Configure MySQL
There are a few minor tweaks I like to make to MySQL. I prefer InnoDB for all my tables by default and need to set the character set to UTF-8. Open up /opt/local/etc/mysql5/my.cnf in your favorite editor (it probably doesn’t exist) and add this:
[mysqld] character-set-server = utf8 collation-server = utf8_general_ci default-storage-engine = InnoDB
That’s it, time to cycle MySQL:
sudo port unload mysql5 sudo port load mysql5
Install Additional PHP Extensions
My typical set of PHP extensions is:
sudo port install php5-curl php5-gd php5-iconv php5-imagick php5-imap php5-mbstring php5-mcrypt php5-mysql php5-pcntl php5-posix php5-soap php5-sockets php5-sqlite php5-xmlrpc php5-xsl
When the install is done cycle Apache again:
sudo port unload apache2 sudo port load apache2
Final Tools
My final tools include Subversion and Git. Feel free to tack on anything else you need:
sudo port install subversion +bash_completion git-core +bash_completion+svn
And bingo, we’re done. Happy developing!