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:

  1. Apache
  2. Base PHP
  3. mod_fcgid
  4. Configure and test these 3
  5. MySQL client and server
  6. Configure MySQL
  7. Assorted additional PHP extensions including php-mysql now that the server is installed.
  8. 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!

Originally published and updated .