The ultimate development environment for Mac OS X

Updated: December 26, 2018

I’ve pieced together what I think is the ultimate development setup. This tutorial is particularly useful if you’re working in different places and have to rely on public wifi or if you don’t have high speed internet available.

As you may have read I’ve moved to the Philippines. This means I no longer have a home address for a while. This also means that high speed internet becomes a luxury. To not being hindered in developing things like AdRotate and other plugins I needed a fast and reliable alternative for my online development server. So that even if internet is wonky, I can still do some work.

What are we going to make

We’re going to set up Homebrew, DnsMasq, Apache2, PHP, MySQL, Sequel Pro and Coda 2 on a Mac with macOS Yosemite or newer (I use macOS Mojave) to work with a development domain name and basic project ‘management’ via Finder.

What do we need

We’ll be installing some software. Most of it is free. Coda 2 is a paid app, but you can use whatever editor you prefer. I just like Coda.

  • A Mac, I will be using my Macbook Pro for this
  • Internet to download a bunch of software
  • An iCloud/App Store account
  • Some understanding of command line and how to use it
  • 1 to 2 hours of your time

Installing Homebrew and Xcode

You’ll want Xcode for it’s command line tools. Which requires Xcode itself. You can grab Xcode from the App Store. This will take a while, the installation is over 2 Gigabyte unfortunately.

Once that’s installed you’ll need to install the Developer command line tools.
You can do that from within Xcode if it asks you, or you can run the following command:
xcode-select --install

This will prompt you with a download screen. Click ‘Download’ and wait for it to finish.
To use the Developer Tools you’ll need to start Xcode once and click ‘Agree’ for their License Agreement. You don’t have to do anything else in there. Just click ‘Agree’ and quit Xcode.

Once done you can continue with HomeBrew. This is a package manager for macOS. I’m not overly familiar with this but from what I gather you can install a ton of extra stuff with it. We just need Homebrew and DnsMasq.

To install Homebrew, run this command:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

dnsmasq

Dnsmasq is a neat little tool to use any domain (also fake ones) on your localhost setup.
Of-course you can just edit your /etc/hosts file and add a few subdomains in there manually. But I’m lazy and want to automate that stuff.

The easiest way is to use a wildcard so you can use *.tld instead of having to set that up manually. This is where dnsmasq is used for.

For our setup we’ll create *.test. This allows us to use anything.test as a localhost domain.

[box type=”info”]Update: Google took control of the .dev TLD a while ago. Starting with Chrome 63 (and other browsers that follow the Preloaded HSTS standard) it’s no longer a valid thing to use for private use.[/box]

Set up and configure dnsmasq with the following:
brew install dnsmasq
cd $(brew --prefix)
mkdir etc
echo 'address=/.test/127.0.0.1' > etc/dnsmasq.conf
sudo cp -v $(brew --prefix dnsmasq)/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo mkdir /etc/resolver
sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'

And that’s dnsmasq done. If you did it correctly you can test this out as soon as you start Apache2. Just type in something.test or yourname.test and it should not produce errors ๐Ÿ™‚

Set up Apache2

Apache is already installed on macOS. But it needs some setting up to whip it into shape. We’ll set up Apache to look for it’s site files in ~/Sites/Localhost and redo some settings so permissions aren’t an issue.

If you don’t have a folder named Sites in your user folder create one.
Inside the ~/Sites folder create a folder named Localhost (notice the capitals!)

Start Apache

To start Apache you run:
sudo apachectl start

Simple… Now you can access http://localhost/ and http://things.test (or whatever word followed by .test) and it should tell you that ‘It Works!’.
With just this command Apache should remain active, even after a reboot.

httpd.conf

To make Apache work the way we need it to a few things need to be enabled, re-done and changed.
I’ll use Nano for my command line editing, but use whatever you prefer.

Open up httpd.conf:
sudo nano /private/etc/apache2/httpd.conf

First enable PHP and vhosts. Look for these lines (or their very similar equivalents):
#LoadModule php5_module libexec/apache2/libphp5.so
#LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.so
#LoadModule mod_rewrite libexec/apache2/mod_rewrite.so

And remove the # at the start. The lines are close to eachother, but not directly under eachother.

Note: macOS Mojave comes with PHP 7.1, not PHP 5.

You also may want to remove a restriction where Apache can’t access anything on your computer.
Never do this on a ‘live’ server though.

Comment out (Add a # at the start of each line) the following lines:
<Directory />
AllowOverride none
Require all denied
</Directory>

To prevent ServerName errors you’ll want to look for the ServerName and change it to:

ServerName localhost

This line may be commented out, in that case uncomment it of-course.

Next, to allow Apache to actually ‘handle’ files you need to change the user and group permission. This is useful for when you install something like WordPress and want to do an update or edit a file from your dashboard.

Look for:
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User _www
Group _www
</IfModule>

And change it to:
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User USERNAME
Group staff
</IfModule>

Where, USERNAME will be the name of your home folder.

And, lastly, way down in the file you need to allow the configuration file for vhosts:

#Include /private/etc/apache2/extra/httpd-vhosts.conf

Also here, remove the # at the start.
This will tell Apache to load the httpd-vhosts file.

httpd-vhosts.conf

Next we’ll edit the httpd-vhosts.conf file.
Open up the file:

sudo nano /private/etc/apache2/extra/httpd-vhosts.conf

Replace the example configuration (or rewrite it) with the following:
<Directory "/Users/USERNAME/Sites/Localhost">
Options Indexes MultiViews FollowSymlinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>

<Virtualhost *:80>
VirtualDocumentRoot "/Users/USERNAME/Sites/Localhost/home"
ServerName home.test
UseCanonicalName Off
</Virtualhost>

<Virtualhost *:80>
VirtualDocumentRoot "/Users/USERNAME/Sites/Localhost/%1"
Servername sites.test
ServerAlias *.test
UseCanonicalName Off
</Virtualhost>

Swap out USERNAME with your username, this is the name of your home folder.
You’ll see that we direct Apache to use the earlier created ~/Sites/Localhost/ folder. Inside it Apache will look for a home folder for the main project page. And all others rely on the 3rd vhost with the wildcard.

Restart Apache

And finally, to apply all the changes you’ve made restart Apache.

sudo apachectl restart

Set up PHP error logging

PHP, as you probably figured, is already installed on macOS. But it doesn’t log errors. To fix this you need to create an php.ini file and change 2 or 3 settings in there.

In macOS the php.ini file is a default version called php.ini.default.

To have PHP recognize your changes you need to copy this file to php.ini.
Open Terminal and run:
sudo cp /etc/php.ini.default /etc/php.ini

Then, edit the newly created php.ini file.
sudo nano /etc/php.ini

And scroll down about halfway to the “Error Handling & Logging” section.
Make sure the following settings are set up like this:
display_errors = On
log_errors = On
error_log = "/private/var/log/apache2/error_log"

This will make errors go into the normal apache2 error_log file in macOS. You can read this file via the macOS console app under /var/log/apache2. If you like you can use a different path of-course. That’s up to you.

MySQL

You probably need MySQL, I know I do… For this I simply installed the MySQL Package available here.
It’s easiest to use the Mac OS X 10.9 (x86, 64-bit), DMG Archive. Which works fine for macOS Sierra. Or any newer version that matches your macOS version.

The MySQL account they want you to have is optional. You can click on No thanks, just start my download. below it to bypass registration.

Once downloaded, open up the DMG file and install MySQL. Really easy.
After the installation completes you will have a new Preference Pane called MySQL in System Preferences. From here you start and stop MySQL Server.
For me, the automatic start up checkbox doesn’t work. But your milage may vary.

MySQL requires little configuration. You can dig up the my.cnf and do some things with it. But that’s beyond the scope of this tutorial. Defaults work pretty well for most people.
You do need to set up a root password for the server which you can do with the following command:

/usr/local/mysql/bin/mysqladmin -u root password 'YOURPASSWORD'

Obviously make sure you use a password other than YOURPASSWORD.
This account can be your main thing to use for your project sites also if you want.

Note: If this initial setup doesn’t work. Check out my root password reset guide here.
Unfortunately MySQL 5.7.24 requires the convoluted reset method. Possibly MySQL 8.0 might as well. But I didn’t test that.

Project Page

As you saw in the httpd-vhost.conf file we created a home.dev site. This will be our landing page if you will. You can use this, or skip it. But I found it a fun experiment and it looks kinda cool.

project-page

In Finder navigate to ~/Sites/Localhost and create a folder called home. In there you can create a simple website to list all other sites.
If you want a page as depicted above you can download this homedev.zip file and use it.

The script will pick up any sub-folders in the ~/Sites/Localhost folder and list them on the page. If there is a WordPress website in the sub-folders it will show a WordPress logo which doubles as a link to the WordPress Dashboard. I have modified the paths and layout to suit this particular setup a bit better.
In the enclosed config.php you need to change the $dir variable to use the correct path. Replace USERNAME with your home folders name. I have added a MySQL Status indicator on there, which you enable from config.php, too.

To add more sites just add a new sub-folder and use that name as your domain name too. I have set up a few in this picture.
homedev

Coda

Coda is my go-to app for everything that involves code. I like the file browser and uploading capabilities. Enough to forgive the silly top bar icon thing, instead of a normal tab-bar. You can buy Coda from www.panic.com. I think it’s well worth the money.

For all projects you add you can use the following settings, just swap out the relevant folder names.

For files:

homedev-files

And MySQL:

homedev-mysql
I don’t use the MySQL option myself, I prefer Sequel Pro for that.

Sequel Pro

Sequel Pro is a free tool to manage MySQL databases with. You can download it here. It is my de-facto tool for databases. I don’t use PHPMyAdmin anymore unless the client’s hosting won’t allow it – And even then, often it’s possible via a SSH tunnel.

The setup is similar to Coda, also here we’re using a Socket instead of a network connection (localhost, yes?). If you leave the Database field empty you can use this single bookmark for the whole setup.

sequelpro

The end… Or start!

And that’s it, you’re now ready to start building websites without the immediate need for Internet, a server or anything online. Aside from maybe php.net as reference ๐Ÿ™‚ But, Coda has a manual built-in I think.