Local LAMP Development on OSX

What's the best way to do web development on OSX? The all in one Apache distribution XAMPP is a solution. More specialized on Drupal, Acquia's Dev Desktop is another one. The most flexible way remains a custom setup like on Linux using the package manager Aptitude. On OSX, a similar package manager is homebrew that can be used to set up a development environment. Inspired by this resource - here is a step-by-step guide to do this:

Use iTerm or Terminal for installation.

 

Upgrade to PHP 7.2.5

https://php-osx.liip.ch

To enable PHP in Apache add the following to httpd.conf and restart Apache:
    LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so
 
    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>
 
Finally, check DirectoryIndex includes index.php
    DirectoryIndex index.php index.html
 
The php.ini and php-fpm.ini file can be found in:
    /usr/local/etc/php/7.2/
 
To have launchd start php now and restart at login:
  brew services start php
Or, if you don't want/need a background service you can just run:
  php-fpm
 
export PATH="$(brew --prefix homebrew/php/php72)/bin:$PATH"
 

wp cli

 
  • Profile hooks: wp profile stage --all --spotlight --allow-root
  • Simulate the loading for a specific URL on the site: 
wp profile hook --all --spotlight --url=https://d30s1b8f4kuhqz.cloudfront.net/wp-admin/admin.php?page=gf_edit_fo... --allow-root
 
wp profile stage --fields=stage,time,cache_ratio
 

wp config

Using a .env file and definitions such as define('DB_NAME', $_SERVER['RDS_DB_NAME']); will cause php warnings:
PHP Warning:  Use of undefined constant DB_NAME - assumed 'DB_NAME' (this will throw an Error in a future version of PHP) in /Users/wohlfarth/Sites/isoc-wp/wp-includes/load.php on line 404
 
To fix these warnings on dev, use define('DB_NAME', 'my-hardcoded-dbname);
 

Install Xcode Command Line Tools

xcode-select --install

Install Homebrew

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Enable Sublime Text as command line editor.

This enables you to edit files using subl filename

ln -s "/Applications/Sublime
Text.app/Contents/SharedSupport/bin/subl" /usr/local/bin/subl

Install required homebrew components

homebrew/dupes/rsync, git, homebrew/php/drush, homebrew/php/phpmyadmin, varnish, mysql. The installed components depend on your personal preference.

brew install yourcomponent

Edit the Apache config file

subl /private/etc/apache2/httpd.conf
# careful, this file can be located elsewhere
/usr/local/etc/httpd/httpd.conf

# to find which config files are included:
apachectl -t -D DUMP_INCLUDES
Included configuration files:
  (*) /usr/local/etc/httpd/httpd.conf

 

Troubleshoot apache errors

tail -f /usr/local/var/log/httpd/error_log

 

and uncomment these lines by removing the #:

LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.so
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
LoadModule php5_module libexec/apache2/libphp5.so
Include /private/etc/apache2/extra/httpd-vhosts.conf
# Add index.php
DirectoryIndex index.html index.php
# if an ssl config is implemented, this needs to be uncommented
Include /private/etc/apache2/extra/httpd-ssl.conf

If you need to swap the PHP version on the command line

export PATH="$(brew --prefix homebrew/php/php56)/bin:$PATH"

If needed, edit the ssl config file

subl /private/etc/apache2/extra/httpd-ssl.conf
# make sure that server certificate and private key are referred to
# IMPORTANT: if the path is incorrect, localhost will simply not be found
SSLCertificateFile "/private/etc/ssl/yourcertificatename.crt"
SSLCertificateKeyFile "/private/etc/ssl/yourkeyname.key"

Create and edit a php.ini file

sudo cp /private/etc/php.ini.default /private/etc/php.ini
subl /private/etc/php.ini
# uncomment these lines:
upload_tmp_dir = /tmp
session.save_path = "/tmp"

Create your local dev site structure

  • /Users/username/Sites/site1
  • /Users/username/Sites/site2
  • /Users/username/Sites/site3
  • etc.

Edit the virtual host config file

subl /private/etc/apache2/extra/httpd-vhosts.conf

Create your virtual hosts

<Virtualhost 127.0.0.1:80>
# Example. If needed add one for ssl on port 443:
  ServerAdmin webmaster@yourdomain
  DocumentRoot /Users/username/Sites/sitefiles
  ServerName local.yourdomain
  DirectoryIndex index.html index.htm index.shtml index.cgi index.php
  AccessFileName .htaccess
  <Directory /Users/username/Sites/sitefiles>
    Options Includes FollowSymLinks Indexes
    AllowOverride All
  </Directory>
  LogLevel warn
  SetEnvIf Request_URI "^/sysadmin\/monitor" nolog
  CustomLog /private/var/log/apache2/access-local.domainname.log common env=!nolog
  CustomLog /private/var/log/apache2/access.log combined env=!nolog
  ErrorLog /private/var/log/apache2/error-local.domainname.log
</Virtualhost>

Add an entry 127.0.0.1 local.domainname for each virtual host: in /private/etc/hosts

Work with MYSQL

# To connect:
    mysql -uroot
# To have launchd start mysql at login/boot:
    mkdir -p ~/Library/LaunchAgents
    ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
# Then to load mysql now:
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
# Or, if you don't want/need launchctl, you can just run:
    mysql.server start
# To stop myslq
    mysql.server stop
# Create a new database
    mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp
# To show mysql info like phpinfo, to show version, location and general tips
    brew info myslq

OS X expects the MySQL socket to sit in /var/mysql, so we create that folder and add a symbolic link to that location:

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

Configuring SSL on local machine

Source: https://gist.github.com/jonathantneal/774e4b0b3d4d739cbc53

Within Terminal, create an SSL directory.
sudo mkdir /private/etc/ssl

Next, generate a private key and certificate for your site.
sudo openssl genrsa -out /etc/apache2/ssl/localhost.key 2048
sudo openssl req -new -x509 -key /private/etc/ssl/localhost.key -out /private/etc/ssl/localhost.crt -days 3650 -subj /CN=localhost

Finally, add the certificate to Keychain Access.
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /private/etc//ssl/localhost.crt

See this for letsencrypt certificates: https://certbot.eff.org/lets-encrypt/osx-apache

and this one: https://letsencrypt.org

Useful mysql and Apache operations

# Start Apache
  sudo apachectl restart
# edit the mysql config
  subl /usr/local/opt/mysql/my-new.cnf
# troubleshoot apache: 
  apachectl configtest - eliminate all error messages there
  sudo vi /var/log/apache2/error_log
  sudo vi /private/var/log/system.log

which php

># check apache version being used: 
which apachectl
php --version php --ini

Troubleshooting

If an ssh connection suddenly requires a password authentication, this is because Apple changed the behaviour of the ssh-agent in macOS Sierra. Now it does not autoload all the keys in the keychain that were added with ssh-add -K, so you must explicitly call ssh-add -A. However, after restarting the machine, required password authentication is back.

The solution is to add the below lines to your .ssh/config file. Create that file if it doesn' exist yet:
 
Host *
  IdentityFile ~/.ssh/id_rsa
  AddKeysToAgent yes

Troubleshooting "Can't connect to server" after an OSX upgrade

This fixed the bigger issue: brew uninstall httpd24
Important: Checking the apache config: sudo apachectl -S
and fix all the errors including tail /private/var/log/apache2/error_log
VirtualHost configuration:
127.0.0.1:443          local.internetsociety.org (/private/etc/apache2/extra/httpd-vhosts.conf:71)
127.0.0.1:80           is a NameVirtualHost
         default server localhost (/private/etc/apache2/extra/httpd-vhosts.conf:22)
         port 80 namevhost localhost (/private/etc/apache2/extra/httpd-vhosts.conf:22)
         port 80 namevhost local.internetsociety.org (/private/etc/apache2/extra/httpd-vhosts.conf:29)
         port 80 namevhost local.ihof (/private/etc/apache2/extra/httpd-vhosts.conf:51)
         port 80 namevhost local.wp.internetsociety.org (/private/etc/apache2/extra/httpd-vhosts.conf:97)
         port 80 namevhost local.terrevirtuelle.com (/private/etc/apache2/extra/httpd-vhosts.conf:113)
         port 80 namevhost local.les-aiguilles-rouges.ch (/private/etc/apache2/extra/httpd-vhosts.conf:133)
         port 80 namevhost local.panopoly (/private/etc/apache2/extra/httpd-vhosts.conf:153)
         port 80 namevhost local.craftcms (/private/etc/apache2/extra/httpd-vhosts.conf:175)
         port 80 namevhost happylager.dev (/private/etc/apache2/extra/httpd-vhosts.conf:195)
         port 80 namevhost local.feincms (/private/etc/apache2/extra/httpd-vhosts.conf:216)
         port 80 namevhost localhost/phpmyadmin (/private/etc/apache2/extra/httpd-vhosts.conf:237)
         port 80 namevhost local.intersect.org (/private/etc/apache2/extra/httpd-vhosts.conf:260)
ServerRoot: "/usr"
Main DocumentRoot: "/Library/WebServer/Documents"
Main ErrorLog: "/private/var/log/apache2/error_log"
Mutex rewrite-map: using_defaults
Mutex default: dir="/private/var/run/" mechanism=default
Mutex mpm-accept: using_defaults
PidFile: "/private/var/run/httpd.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="_www" id=70
Group: name="_www" id=70
bash-3.2#

PHP isn't interpreted on High Sierra

Add these lines in httpd.conf

AddType x-httpd-php .php
AddHandler application/x-httpd-php .php .php5