macOS Local Development Setup

A couple weeks ago I decided to replace MAMP on my MacBook with free tools for local PHP development. I didn’t find a guide online that was perfect for what I wanted, so here are the steps I used, pieced together from several other guides.

Prerequisites

  • This guide was written for macOS 10.14 Mojave. Other versions of macOS may require changes to some of the steps.
  • I use Homebrew to install MySQL and phpMyAdmin.
  • You will need a way to edit files from the command line. I use Atom, which can be used to edit file by running the atom [filename] command.

Apache

macOS Mojave comes with Apache 2.4.34 pre-installed. This isn’t the latest version, but it was good enough for me. If you want to install a newer version, I suggest following the guide on getgrav.org.

Apache Configuration

Edit the Apache httpd.conf file, found here: /etc/apache2/httpd.conf.

We need to enable things like Apache rewriting, includes, user directories, virtual hosts, and PHP. To do so, make sure the following lines are uncommented:

LoadModule authz_core_module libexec/apache2/mod_authz_core.so
LoadModule authz_host_module libexec/apache2/mod_authz_host.so
LoadModule userdir_module libexec/apache2/mod_userdir.so
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
LoadModule include_module libexec/apache2/mod_include.so
LoadModule php7_module libexec/apache2/libphp7.so
Include /private/etc/apache2/extra/httpd-vhosts.conf
Include /private/etc/apache2/extra/httpd-userdir.conf

To have Apache look for PHP indexes, add index.php to the DirectoryIndex. It should look like this:

<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule>

Find the ServerName setting and set it to localhost:

ServerName localhost

Make sure to save and close the file, then restart Apache:

sudo apachectl restart

Here are other commands you might want to know if you need to start or stop Apache:

sudo apachectl start
sudo apachectl stop

Run the Apache configuration test to make sure there are no errors:

apachectl configtest

Apache User Configuration

Open the user home directories configuration file: /etc/apache2/extra/httpd-userdir.conf.

Uncomment the following line to have Apache load configuration files in the users:

Include /private/etc/apache2/users/*.conf

Save and close the file.

Now we need to check to see if a configuration file exists for your user. Run the following command:

ls /etc/apache2/users/*.conf

If a conf file for the current macOS user is not listed, create one:

sudo touch username.conf

Open the username.conf file. To allow the user the proper permissions, add the following to the file:

<Directory "/Users/username/Websites/Path/">
    Options Indexes MultiViews FollowSymLinks
    Require all granted
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

Be sure to change the Directory path to the location where you will store your local websites. Save and close the file.

Restart Apache:

sudo apachectl restart

Hosts

Every time you want to set up a new local project, you will need to add a host to the macOS hosts file and add a virtual host to the Apache httpd-vhosts.conf file. (Note: You can buy a nice app called VirtualHostX to help with this if you don’t want to mess with the command line each time.)

macOS Host

To add a host to macOS, open /etc/hosts, and add the local domain to the file:

127.0.0.1 local.domain.com

A lot of people like to use something like domain.dev or domain.local, but I like to use something like local.domain.com. This way is nice to me because I use 1Password to handle all my passwords, and it will recognize the local domain for stored passwords on the production site.

After making your changes, save and close the file.

Apache Virtual Host

You will now need to add a virtual host to Apache to match the host added to macOS. Open /private/etc/apache2/extra/httpd-vhosts.conf. Add the new VirtualHost to the file:

<VirtualHost *:80>
    DocumentRoot "/Users/Websites/Path/domain.com"
    ServerName domain.com
    ServerAlias local.domain.com
</VirtualHost>

Optionally, you can add virtual host rewriting to load remote images for images missing in the local environment, a trick I used often in MAMP. Here is an example for Drupal uploads:

<VirtualHost *:80>
    DocumentRoot "/Users/Websites/Path/domain.com"
    ServerName domain.com
    ServerAlias local.domain.com
    
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^/sites/default/files/(.*)$
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^/sites/default/files/(.*)$ https://domain.com/sites/default/files/$1 [L]
</VirtualHost>

Restart Apache:

sudo apachectl restart

PHP

macOS Mojave comes with PHP 7.1 pre-installed. Again, this was good enough for me, but if you want to install a newer version (or multiple versions), try following the getgrav.org guide.

PHP Configuration

Create a php.ini file by copying the default configuration file:

sudo cp /etc/php.ini.default /etc/php.ini

Set the proper permissions for the php.ini file:

sudo chmod 644 /etc/php.ini

Open the /etc/php.ini file. Find the error_reporting and display_errors settings and turn them on:

error_reporting = E_ALL | E_STRICT
display_errors = On

Find the date.timezone setting and set the timezone:

date.timezone = America/Chicago

Increase file upload and memory limits to fit your needs:

upload_max_filesize = 128M
post_max_size = 128M
max_execution_time = 300
max_input_time = 300
memory_limit = 128M

Save and close the file.

MySQL

Install MySQL with Homebrew:

brew install mysql

Start MySQL and set it to start at login:

brew services start mysql

Run the MySQL configuration:

mysql_secure_installation

The configuration will now ask a series of questions. I went with the following options:

  • Validate password component: Yes
  • Choose the password validation policy level and set a root password
  • Remove anonymous users: Yes
  • Disallow root login remotely: Yes
  • Remove test database and access to it: Yes
  • Reload privilege tables now: Yes

MySQL on macOS will get a 2002 MySQL socket error that will need to be fixed by running the following commands:

sudo mkdir /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

phpMyAdmin

If you would like to manage your MySQL databases with phpMyAdmin, install phpMyAdmin with Homebrew:

brew install phpmyadmin

Open the Apache configuration file (/etc/apache2/httpd.conf) and add the following to enable access to phpMyAdmin:

Alias /phpmyadmin /usr/local/share/phpmyadmin
<Directory /usr/local/share/phpmyadmin/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Allow from all
    </IfModule>
</Directory>

Save and close the file and then restart Apache:

sudo apachectl restart

Open the phpMyAdmin configuration file (/usr/local/etc/phpmyadmin.config.inc.php) and change localhost to 127.0.0.1 (this prevents an error I was getting):

$cfg['Servers'][$i]['host'] = '127.0.0.1';

Add a secret passphrase:

$cfg['blowfish_secret'] = 'My secret passphrase';

Add a TempDir in the directories section of the config file:

$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
$cfg['TempDir'] = '/tmp';

Save and close the file.

You can now access phpMyAdmin with user root and the password you set during the MySQL configuration:

http://localhost/phpmyadmin/

Authentication Method Error

At this point, I was getting following error when trying to access phpMyAdmin:

mysqli_real_connect(): (HY000/2054): The server requested authentication method unknown to the client

To fix this error, open MySQL:

mysql -u root -p

Run the following command:

ALTER USER 'username'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

Exit MySQL by running the exit command.

Command Aliases

I set up a few aliases in my .bash_profile as shortcuts for managing my local server:

# Apache
alias start-apache='sudo apachectl start'
alias stop-apache='sudo apachectl stop'
alias restart-apache='sudo apachectl restart'

# Config files
alias config-apache="sudo atom /etc/apache2/httpd.conf"
alias config-apache-users="sudo atom /etc/apache2/users/"
alias config-hosts="sudo atom /etc/hosts"
alias config-vhosts="sudo atom /private/etc/apache2/extra/httpd-vhosts.conf"
alias config-php="sudo atom /etc/php.ini"

Resources