Scenario: You’re a PHP developer. (Hey, someone has to write the good PHP code.) You use a mac (and, let’s assume, you’re on Lion). You want to have a lot of sites running locally, with minimum effort. Sure, you could use MAMP, but that’s a chunk of manual configuration every time you want to create a new domain. It’s not much, but it adds up!
Here’s a big pile of steps to get OS X, PHP, Apache, Percona’s MySQL server, and so forth all working smoothly.
First, install homebrew. It makes things much easier. Then update it:
You could install MySQL, or you could install Percona Server instead. It’s transparent, it’s painless, and Percona is (in my experience) somewhere around 30% faster on my MacBook Pro than bare MySQL is. So (assuming you don’t have MySQL installed already):
brew install percona-server # Go to lunch, it takes a bit. brew link percona-server unset TMPDIR mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix percona-server)" --datadir=/usr/local/var/percona --tmpdir=/tmp mkdir -p ~/Library/LaunchAgents cp /usr/local/opt/percona-server/homebrew.mxcl.percona-server.plist ~/Library/LaunchAgents/ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.percona-server.plist
Then you should be able to connect with
Apache and PHP
OS X ships with PHP by default (5.3.10, as of the time of writing), but does not enable it for Apache by default. So, here’s a patch to fix that:
Download and apply with:
cd ~/Downloads curl -LO https://gist.github.com/raw/2931575/a9e424d70fcb71b65c788f71767824c3ec2f605d/httpd.conf.diff cd /etc/apache2 sudo patch -p2 < ~/Downloads/httpd.conf.diff
Then create a personal configuration file, like so:
cd ~/Downloads curl -LO https://gist.github.com/raw/2931635/1311ed82da761b1db7a2cc7127f47dcd6510fa90/YOURNAME.conf sed -e "s/YOURNAME/$(whoami)/g" YOURNAME.conf > $(whoami).conf sudo mv $(whoami).conf /etc/apache2/users
Generate an SSL certificate, following the directions from superuser.com. The configuration file already has the SSL directives in it; you should put the resuling server.crt and server.key files in /etc/apache2, or edit the configuration file appropriately.
(The SSL configuration, at this time, is set up only for
domain.dev use, not
domain.10.0.0.10.nip.io use. You can switch out the VirtualDocumentRoot line in the
*:443 VirtualHost block for the one in the
ServerName example.127.0.0.1.nip.io block if you need to use SSL for mobile testing.)
Finally, start up Apache – open up the Sharing preference pane and check (or uncheck and recheck) Web Sharing.
.local domain is special in OS X, and you should avoid it. Instead, set up a
.dev wildcard domain with dnsmasq:
brew install dnsmasq cat <<EOT > /usr/local/etc/dnsmasq.conf address=/.dev/127.0.0.1 rebind-domain-ok=/xip.io/nip.io/ EOT sudo cp /usr/local/opt/dnsmasq/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
dnsmasq will still let you edit /etc/hosts to make changes – in fact, it works better, since it picks up changes faster than the OS would otherwise.
Now you need to tell OS X to use dnsmasq as one of its domain nameservers. You could just go into the Network preference pane and add it to your DNS servers, but if you don’t set all of your DNS servers, you can’t resolve things properly, and if you do set all of them, then you have to reset them if you go somewhere with a captive portal wifi (many coffee shops and hospitals, for instance) – it’s a pain. A little more work on the front end removes this problem basically entirely.
You’ll need these two files:
Download and extract, then:
mv setdns.sh /usr/local/bin chmod a+x /usr/local/bin/setdns.sh sudo cp com.zizproductions.setdns.plist /Library/LaunchDaemons sudo launchctl load -w /Library/LaunchDaemons/com.zizproductions.setdns.plist
This will watch for changes in your network configuration and add
127.0.0.1 (your dnsmasq server) to the list of nameservers if it needs to.
One more thing. OS X will refuse to do DNS lookups if you’re not connected to a network (under some circumstances). There’s a simple way around that, in two steps:
First, install VirtualBox. Create a new virtual machine, and give it a Host-only network adapter. (You can use the FreeDos image, if you don’t actually need a virtual machine for anything. It’s small.) Start the virtual machine at least once.
You can do this from the commandline with this snippet (after VirtualBox is installed):
(ifconfig | grep -s vboxnet) || VBoxManage hostonlyif create ipconfig vboxnet0 --ip 192.168.56.1 --netmask 255.255.255.0
This prevents OS X from disabling normal DNS resolution when you’re not connected to a network.
Second, create a ‘dev’ domain resolver entry:
sudo mkdir -p /etc/resolver sudo tee /etc/resolver/dev <<EOT nameserver 127.0.0.1 domain dev search_order 1 EOT
This tells OS X that it can always ask localhost (your dnsmasq server) for domain resolution for
.dev domains when it doesn’t have other DNS servers.
Now if you type
ifconfig in a terminal, one of the lines should start with
vboxnet0: – if it does, great! OS X will happily do DNS lookups even if you’re on an airplane, so you can keep using your
.dev domains wherever you are.
Yes, that’s all. Now you can copy your html5boilerplate in, or check out WordPress, or whatever you need to do, and
http://testdomain.dev/ should take you right there. (Remember, if you’re in Chrome, you’ll need to type
http:// explicitly – just typing in
testdomain.dev will do a google search.)
And that’s it!
Newer versions of homebrew link the current version of a package into
/usr/local/opt, avoiding the need for the
Fixed an issue with local DNS resolution not working when disconnected from a network.
All instructions, commands, source, and configuration files provided in this post and authored by me are available for use under the terms of the MIT license, including the disclaimer of warranty.
Further Disclaimer: These instructions are from notes and my own installation journal. Your mileage may vary.