Setting up Apache + PHP + MySQL on OSX with Homebrew

Some time ago I was doing some hacking for Chamilo LMS (a Free Software E-Learning system) which uses a classic web environment consisting of Apache + PHP + MySQL. Setting this up in GNU/Linux is trivial, but a MacBook with OSX (now macOS) is a different story.

After some trial and error, I settled on a pure Homebrew installation and decided to write this blog post to help others in a similar situation.

Stay inside and write some code.
Stay inside and write some code.

Why Homebrew?

My first google searches led me to MAMP, an OSX bundle with Apache + MySQL + PHP. However MAMP had many weird quirks that forced me to maintain a local set of patches just to get things working predictably.

The other popular alternative for a web environment consisted of mixing OSX’s included Apache with software patched in from Homebrew. That meant modifying files in /etc, and mixing software from two completely different sources.

Overall it sounded like a very bad idea because you can’t just apt-get install --reinstall if you break something in OSX.

In summary, these are the reasons why I preferred a pure Homebrew installation:

  • No need for root. Everything is user–writable in /usr/local.
  • Vanilla versions for everything, and easy to keep the individual components up–to–date with upstream, or mix different versions if you want.
  • Easy to destroy and replicate with a guide like this, in case you break something.
  • Usable, non–root, PEAR system for installing PHP stuff.
  • The popular “patched-in” setups make you brew almost all this anyway, so better go the extra mile and have a more reliable system.

I couldn’t find a simple and clean tutorial that didn’t reinvent the wheel so here’s my own tutorial to get Apache + MySQL + PHP running on OSX, using only Homebrew.

By the way: For this guide I assume you know your way around a terminal, at least enough to use something like Homebrew.

#1- Install Homebrew

First of all you need to install Homebrew. Head over to Homebrew’s homepage for instructions.

Before brewing any software it’s a good idea to run a health check, and a quick update & upgrade just to make sure we are not missing anything new:

$ brew doctor
$ brew update && brew upgrade

Pay attention to whatever that says and follow any instructions. In case something seems wrong you can check Homebrew’s installation instructions for troubleshooting.

Also, you need to add this to your .bash_profile, to make sure you use Homebrew’s installed binaries instead of your system’s pre installed ones (specially important for PHP-FPM).

# Include Homebrew's sbin path

#2- Install Apache (httpd24) and PHP

We’ll begin by installing (brewing) Apache 2.4 and PHP 7.0:

$ brew install homebrew/apache/httpd24
$ brew install homebrew/php/php70

This will take a few minutes, you’ll see a summary of each operation after each command finishes.

Remember that if you face any issues along this process you can consult the brew info command for any package and get some extra tips and information. For example PHP’s info has some useful tips for PEAR users (we won’t cover PEAR in this guide):

$ brew info php70

After Apache and PHP are done, we can add phpmyadmin into the mix:

$ brew install phpmyadmin

phpmyadmin is a web app that helps you administer your MySQL installation, it’s a must have if you’ll be working with MySQL.

#3- Configuring Apache 2.4 to use PHP-FPM, and a user controlled DocumentRoot

We’ll configure a VirtualHost in Apache that uses PHP, and also sets a user controlled DocumentRoot instead of the traditional location inside /usr/local/opt/httpd24.

I prefer to keep things in my user directory and outside /usr/local/ so I can quickly browse my code and files in Finder if I have to.

To get this set let’s go and edit /usr/local/etc/apache2/2.4/extra/httpd-vhost.conf.

Replace the existing VirtualHost configuration for the following. Make sure to edit things as you see fit. At the very least make sure the paths exist:

<VirtualHost *:8080>
<FilesMatch \.php$>
# 2.4.10+ can proxy to unix socket
# SetHandler "proxy:unix:/var/run/php5-fpm.sock|fcgi://localhost/"

# Else we can just use a tcp socket:
SetHandler "proxy:fcgi://"

<IfModule dir_module>
DirectoryIndex index.html index.php

ServerAdmin [email protected]
DocumentRoot "/Users/YOUR-USER-NAME/Sites"
ServerName localhost
ServerAlias localhost
ErrorLog "/Users/YOUR-USER-NAME/Sites/logs/localhost-error_log"
CustomLog "/Users/YOUR-USER-NAME/Sites/logs/localhost-access_log" common

<Directory /Users/YOUR-USER-NAME/Sites>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted

# PHPMyAdmin
Alias /phpmyadmin /usr/local/share/phpmyadmin
<Directory /usr/local/share/phpmyadmin/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted

Now let’s make sure the main Apache configuration is using our new VirtualHost configuration, and that the proper modules are loaded.

Edit /usr/local/etc/apache2/httpd.conf and make sure the following lines are not commented (they are already present but commented with a ‘#’ symbol):

LoadModule proxy_module libexec/
LoadModule proxy_fcgi_module libexec/
LoadModule rewrite_module libexec/

Include /usr/local/etc/apache2/2.4/extra/httpd-vhosts.conf

For extra credit let’s edit PHP’s configuration to have a default time zone. This helps when you are debugging code that doesn’t set a timezone explicitly. It makes PHP print timestamps in your local time.

Edit /usr/local/etc/php/7.0/php.ini and make sure to edit the date.timezone line, like this:
date.timezone = America/Lima (or whatever works for you)

#4- Setting up MySQL

The last piece we need is MySQL:
$ brew install mysql

After that installs we’ll secure the server a little bit by running:
$ brew services start mysql
$ mysql_secure_installation

By the way, brew services controls services installed through Homebrew. You can see what’s available and its status running:

$ brew services list

#5- Profit

Now let’s see if everything is working.

You can create an index.php file with a call to phpinfo(); inside your configured root (probably /Users/YOUR-USER-NAME/Sites) to test if PHP is working fine and what modules are being loaded into it.

Let’s start the Apache and PHP services:

$ brew services start httpd24
$ brew services start php70

(Note that for whatever reason brew services does not print out an error if Apache fails to start. If at this point there’s any problem it’s probably with the Apache configuration, so a syntax check with apachectl -S might help you.)

If everything went well you can open http://localhost:8080/ and http://localhost:8080/phpmyadmin in your browser and try out PHP and MySQL respectively.

This looks like a lot of work, but it’s fairly quick with this cheat sheet, in the long run it’s much safer and easier to maintain and adapt thanks to brew’s excellent tools. A quick brew update && upgrade will take care of updating you to the latest versions of everything.

Happy hacking!

Last updated on 2016-12-22: Apache 2.4.23, PHP 7.0.14, MySQL 5.7.16 and OSX 10.12.2.

11 thoughts on “Setting up Apache + PHP + MySQL on OSX with Homebrew

  1. So, I’ve followed all these steps and everything looks to be in place. However, when I enter “apachectl start” as best I can tell, its still the native OS X copy of apache thats running. Is this a PATH issue? Greatful for any help you can offer.

    1. Paul you are probably missing something like this in your .bash_profile:

      Notice the added /usr/local paths. I don’t remember if brew does this automatically, specially the sbin path.

      Restart your terminal and try again, you can see which version is being used with:
      which apachectl

  2. Thanks for this!

    I had to install php with `–homebrew-apxs` to avoid the following cryptic error when starting apache:

    httpd: Syntax error on line 117 of /usr/local/etc/apache2/2.2/httpd.conf: Cannot load /usr/local/Cellar/php56/5.6.3/libexec/apache2/ into server: dlopen(/usr/local/Cellar/php56/5.6.3/libexec/apache2/, 10): Symbol not found: _ap_unixd_config\n Referenced from: /usr/local/Cellar/php56/5.6.3/libexec/apache2/\n Expected in: /usr/local/Cellar/httpd22/2.2.29/bin/httpd\n in /usr/local/Cellar/php56/5.6.3/libexec/apache2/

Comments are closed.