Apache2, PHP and MySQL on Mac OSX
I recently setup the so-called “MAMP” (MacOSX, Apache2, MySQL and PHP) on my laptop, so I can have a portable web development environment. I decided to use MacPorts (formerly DarwinPorts) for Apache2 and PHP5, which makes things a lot easier. There were a few “gotchas” though, so I thought I’d share what I learned. If you want an installation completely based on MacPorts builds, this site has some good instructions.
I went with the binary installation package from MySQL.com, instead of using the MacPorts version, for aesthetic reasons: it comes with a cool preference panel component for starting and stopping the server (click the thumbnail to the right for a larger image). Using this version instead does require a slight tweak to get the MacPorts packages to link to it, but its easy to do.
While you’re at MySQL.com, I highly recommend that you also download MySQL Administrator. I’ve never been a big fan of GUI database interfaces, but this is a sweet application, and well worth having.
Once you have MySQL up and running, install Apache2. I don’t know why Apple still ships OSX with Apache 1.x; Apache 2.x has been out for a long time now, and has many improvements over version 1. To install Apache2, run (in Terminal, duh):
sudo port -v install apache2
It installs into /opt/local/apache2. The one thing I dislike about DarwinPorts is the oddball location of /opt/local. Why not just /opt? Adding a /local sub-directory to /opt seems completely redundant.
If you want the System Preferences controls for the webserver to work with the newly installed Apache2, you’ll have to make some minor system changes. I think its worthwhile. Note, however, that future updates from Apple could overwrite these changes, and so you’ll have to redo them if that happens. First, shut down the native Apache1. Open the Sharing panel in System Preferences, click on “Personal Web Sharing”, then click the Stop button if it is running. Next, from the command line (Terminal) move the apachectl binary out of the way and create a link to the new one:
sudo bash
cd /usr/sbin
mv apachectl apachectl.mac
ln /opt/local/apache2/bin/apachectl .
cd /opt/local/apache2/bin
cp apachectl apachectl.bak
I made a backup copy of the apachectl in /opt/local/apache2/bin just in case a system update from Apple over-writes it.
Next, copy /opt/local/apache2/conf/httpd.conf.sample to /opt/local/apache2/conf/httpd.conf, and open the new file in a text editor (using a text editor that saves in plaintext format — do not use TextEdit, since it saves in Rich Text). I changed mine so that the new Apache will work as the system expects the old one to work. Here are the lines that I changed and/or added:
ServerAdmin <my email address>
ServerName <my server's name>
PidFile "/private/var/run/httpd.pid"
DocumentRoot "/Library/WebServer/Documents"
# This should be changed to whatever you set DocumentRoot to.
#
#<Directory "/opt/local/apache2/htdocs">
<Directory "/Library/WebServer/Documents">
...
</Directory>
DirectoryIndex index.html index.php
ErrorLog "/private/var/log/httpd/error_log"
CustomLog "/private/var/log/httpd/access_log" common
Include conf/extra/httpd-userdir.conf
Now you should be able to re-enable “Personal Web Sharing” in System Preferences, and have the new Apache working just like the old one.
The final step is to compile and install PHP5 using DarwinPorts. Before you do, however, it is necessary to modify the port’s Portfile file so that it links to the MySQL 5 install that resides in /usr/local. Make a backup of it first:
cd /opt/local/var/db/dports/sources
cd rsync.rsync.darwinports.org_dpupdate_dports/www/php5/
cp Portfile Portfile.bak
Open the Portfile with your favorite text editor and remove the line “–without-mysql”. Add two new lines:
--with-mysql=/usr/local/mysql \
--with-mysql-sock=/private/tmp/mysql.sock \
Now run the port command to download, compile and install PHP5 as a module for our new Apache2:
sudo port -v install php5 +apache2
Now all you need to do is run the command that DarwinPorts suggests, and include the new configuration information in your httpd.conf file. So run:
cd /opt/local/apache2/modules
sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.so
And add this line to the bottom of the /opt/local/apache2/conf/httpd.conf file:
Include conf/extras-conf/mod_php.conf
Thats it! The installation is done. You might want to tweak the php defaults by copying /opt/local/etc/php.ini-dist to /opt/local/etc/php.ini and adjust to taste. If you use the PEAR extensions, you can customize its defaults by copying /opt/local/etc/pear.conf.sample to /opt/local/etc/pear.conf and editing as needed. Happy developing!

April 1st, 2007 at 10:40 am
You may want to enable SSL (https) on your local apache install. To do that, you need to generate a few SSL certificates. Darwin/Macports installed the openssl config files into /opt/local/etc/openssl. Change into that directory, and edit the openssl.cnf file. I changed or added these lines:
dir = ./CA # Where everything is kept
default_days = 1365 # how long to certify for
countryName_default = CA
stateOrProvinceName_default = Alberta
localityName_default = Banff
0.organizationName_default = NetMojo
commonName_default = localhost
emailAddress_default = me@localhost
Next, edit misc/CA.pl. I changed these lines:
$DAYS="-days 1365"; # 3.74 years
$CATOP="./CA";
$DIRMODE = 0755;
Generate a new Certificate Authority (CA), Certificate Request (a.k.a. private key, for our purposes), and Certificate. Keep this in mind:
* use a password you’ll remember
* press Enter to accept the defaults from openssl.cnf
* skip the challenge password by pressing Enter
sudo misc/CA.pl -newca
sudo misc/CA.pl -newreq
sudo misc/CA.pl -signreq
Rename the files to something more appropriate:
sudo mv newkey.pem localhost-key.pem
sudo mv newcert.pem localhost-cert.pem
Unencrypt the private key, so you don’t have to enter a password everytime that apache starts up:
sudo openssl rsa -in localhost-key.pem -out localhost-unenc-key.pem
sudo chown www localhost-unenc-key.pem
sudo chmod 0400 localhost-unenc-key.pem
Now edit the file /opt/local/apache2/conf/extra/httpd-ssl.conf. Here are the lines that I changed:
SSLCertificateFile /opt/local/etc/openssl/localhost-cert.pem
SSLCertificateKeyFile /opt/local/etc/openssl/localhost-unenc-key.pem
SSLCACertificateFile /opt/local/etc/openssl/CA/cacert.pem
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512
SSLSessionCache shmcb:/private/var/log/httpd/ssl_scache(512000)
SSLMutex file:/private/var/log/httpd/ssl_mutex
DocumentRoot "/Library/WebServer/Documents"
ServerName localhost:443
ServerAdmin me@localhost
ErrorLog /private/var/log/httpd/ssl_error_log
TransferLog /private/var/log/httpd/ssl_access_log
CustomLog /private/var/log/httpd/ssl_request_log \
And finally, edit the /opt/local/apache2/conf/httpd.conf file and uncomment the include line:
# Secure (SSL/TLS) connections
Include conf/extra/httpd-ssl.conf
That should be all. Start up apache and check the log files in /private/var/log/httpd. My error_log says:
[Sun Apr 01 11:49:18 2007] [notice] Digest: generating secret for digest authentication ...
[Sun Apr 01 11:49:18 2007] [notice] Digest: done
[Sun Apr 01 11:49:18 2007] [notice] Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e
DAV/2 PHP/5.2.1 configured -- resuming normal operations
And my new ssl_error_log has a warning:
[Sun Apr 01 11:49:17 2007] [warn] RSA server certificate is a CA certificate
(BasicConstraints: CA == TRUE !?)
And https://localhost works. Enjoy!
April 9th, 2007 at 9:15 pm
I discovered a problem with my binary MySQL installation: it breaks some functionality in ‘curl’ that in turn breaks PEAR. Running ‘pear’ produces:
PHP Fatal error: Unable to start curl module in Unknown on line 0
This blog points out the reason:
I’m pretty sure that work around will be to recompile PHP and possibly curl to link against a Macports version of mysql — although I still intend to keep using the binary install from mysql. I’ll have to build mysql so that it uses the same socket destination as the binary install; either that or modify the start up scripts of the binary install to use the default socket location of the Macports install. I’m not sure when I’ll deal with this…
April 17th, 2007 at 12:45 pm
Picking up on that thread, I updated my install of Macports, and edited the MySQL5 Portfile so that it uses the same location for the socket file as the binary install.
The Portfile is in /opt/local/var/db/dports/sources/rsync.rsync.darwinports.org_dpupdate_dports/databases/mysql5, and the line to change is:
--with-unix-socket-path=/private/tmp/mysql.sock \
This should allow software linked to this client to access the running MySQL daemon from the binary version. Build & install:
sudo port -v install mysql5
Then rebuild and reinstall any libraries or programs that were linked to mysql. For me, thats curl, php and ruby…
sudo port -v uninstall curl
sudo port -v install curl +openssl +mysql5
sudo port -v uninstall php5
sudo port -v install php5 +apache2 +mysql5
sudo port -v uninstall rb-rubygems
sudo port -v uninstall ruby
sudo port -v install ruby +apache2 +mysql5
sudo port -v install rb-rubygems