THIS GUIDE IS OLD! Go to http://echo.co/blog/os-x-1010-yosemite-local-development-environment-apache-php-and-mysql-homebrew for the Yosemite version.
Go to http://developer.apple.com/downloads, log in with your Apple ID (free) and download the newest version of either Command Line Tools (OS X Lion) for Xcode or Command Line Tools (OS X Mountain Lion) for Xcode. Run the installer in the dmg and you'll have the LLVM compiler, make
, and other build tools.
Install XQuarts to satisfy a library dependency for PHP.
Open terminal and run the following steps in the command prompt to install brew
and bring it up to date:
ruby <(curl -fsSkL raw.github.com/mxcl/homebrew/go)
brew doctor
brew update
Edit ~/.bash_profile
and put /usr/local/bin
at the beginning. This command attempts to do this automatically:
echo "PATH=\$(echo \$PATH | sed 's|/usr/local/bin||; s|/usr/local/sbin||; s|::|:|; s|^:||; s|\(.*\)|/usr/local/bin:/usr/local/sbin:\1|')" >> ~/.bash_profile && source ~/.bash_profile
brew install mariadb
MariaDB may use cmake
as part of its compilation process, and cmake has java
as a dependency. If this pops up during the MariaDB build, choose to Install:
Set up MariaDB, set to start on boot, and start now:
unset TMPDIR
mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mariadb)" --datadir=$(brew --prefix)/var/mysql --tmpdir=/tmp
cp -v $(brew --prefix mariadb)/support-files/my-small.cnf $(brew --prefix mariadb)/my.cnf
sed -i "" 's/max_allowed_packet = 1.*M/max_allowed_packet = 2G/g' $(brew --prefix mariadb)/my.cnf
egrep "^# Uncomment the following if you are using InnoDB tables$" $(brew --prefix mariadb)/my.cnf &>/dev/null && sed -i '' "s/^\(# Uncomment the following if you are using InnoDB tables\)$/\1@innodb_file_per_table/; y/@/\n/; s/^#\(innodb_.*\)/\1/g" $(brew --prefix mariadb)/my.cnf
[ ! -d ~/Library/LaunchAgents ] && mkdir -v ~/Library/LaunchAgents
[ -f $(brew --prefix mariadb)/homebrew.mxcl.mariadb.plist ] && cp -v $(brew --prefix mariadb)/homebrew.mxcl.mariadb.plist ~/Library/LaunchAgents/
[ -f ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist ] && launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist
$(brew --prefix mariadb)/bin/mysql_secure_installation
NOTE: These instructions are for PHP 5.3. If you want PHP 5.4, change all instances of php53
to php54
, and 5.3
to 5.4
. If you want to later switch from php53 to php54, you would need to run brew unlink php53 && brew link php54
for brew to symlink the appropriate files in /usr/local/bin.
Add the dupes and php taps:
brew tap homebrew/dupes
brew tap josegonzalez/php
Install PHP:
brew install php53 --with-mariadb --with-intl --with-imap --with-fpm
Set timezone, and increase timeouts and memory values (this is a single command):
sed -i '-default' "s|^;\(date\.timezone[[:space:]]*=\).*|\1 \"`systemsetup -gettimezone|awk -F"\: " '{print $2}'`\"|; s|^\(memory_limit[[:space:]]*=\).*|\1 256M|; s|^\(post_max_size[[:space:]]*=\).*|\1 200M|; s|^\(upload_max_filesize[[:space:]]*=\).*|\1 100M|; s|^\(default_socket_timeout[[:space:]]*=\).*|\1 600|; s|^\(max_execution_time[[:space:]]*=\).*|\1 300|; s|^\(max_input_time[[:space:]]*=\).*|\1 600|;" $(brew --prefix)/etc/php/5.3/php.ini
Add a PHP error log; without this, you may get Internal Server Errors if PHP has errors to write and no logs to write to (be sure to copy and paste the lines containing USERHOME
through the last EOF
as a single command):
USERHOME=$(dscl . -read /Users/`whoami` NFSHomeDirectory | awk -F"\: " '{print $2}') cat >> $(brew --prefix)/etc/php/5.3/php.ini <<EOF
; PHP Error log
error_log = ${USERHOME}/Sites/logs/php_error_log
EOF
Install PHP extensions and add configuration to php53:
brew install php53-uploadprogress php53-apc php53-memcache php53-xdebug php53-xhprof
sed -i '' "s|^\(apc\.shm_size=\)[0-9]*M$|\1256M|; s|^\(apc.num_files_hint=\)[0-9]*|\10|;" $(brew --prefix)/etc/php/5.43/conf.d/ext-apc.ini
echo "memcache.hash_strategy=\"consistent\"" >> $(brew --prefix)/etc/php/5.3/conf.d/ext-memcache.ini
Start PHP-FPM and start on boot:
[ ! -d ~/Library/LaunchAgents ] && mkdir -p ~/Library/LaunchAgents
cp -v $(brew --prefix php53)/homebrew-php.josegonzalez.php53.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew-php.josegonzalez.php53.plist
Note that even though php-fpm.conf has _www as the user and group, it will run as your user because you're not loading the plist as root.
Also, php-fpm.conf
is pre-configured to have min-servers, kind of like Apache, which are unnecessary on a laptop where you should never be loading more than 2 pages at a time. Consider changing pm = dynamic
to pm = ondemand
. The comments around that section will explain how to lower the maximum number of FPM processes, which I'd recommend setting to 2, and the timeout value to 5s. PHP-FPM will have to start processes more often, but it'll also kill idle processes when they're no longer needed, saving RAM.
Add the apache tap:
brew tap homebrew/apache
Due to a bug in OS X's apr-1-config tool, this will create symlinks for the non-existent OSX10.8.xctoolchain directory. You're welcome to try the following brew command without this, but you'll need to run this if it fails to install:
[ "$(sw_vers -productVersion | sed 's/^\(10\.[0-9]\).*/\1/')" = "10.8" ] && bash -c "[ -d /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain ] && sudo bash -c 'cd /Applications/Xcode.app/Contents/Developer/Toolchains/ && ln -vs XcodeDefault.xctoolchain OSX10.8.xctoolchain' || sudo bash -c 'mkdir -vp /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain/usr && cd /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain/usr && ln -vs /usr/bin'"
We'll use mod_fastcgi
to run PHP with PHP-FPM:
brew install mod_fastcgi
Create the logs directory:
[ ! -d ~/Sites/logs ] && mkdir -pv ~/Sites/logs
VirtualHosts (be sure to copy and paste the lines containing USERHOME
through the last EOF
as a single command):
touch ~/Sites/httpd-vhosts.conf
sudo ln -s ~/Sites/httpd-vhosts.conf /etc/apache2/other/httpd-vhosts.conf
USERHOME=$(dscl . -read /Users/`whoami` NFSHomeDirectory | awk -F"\: " '{print $2}') cat > ~/Sites/httpd-vhosts.conf <<EOF
#
# Use name-based virtual hosting.
#
NameVirtualHost *:80
#
# Set up permissions for VirtualHosts in ~/Sites
#
<Directory "${USERHOME}/Sites">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>
# For http://localhost in the OS X default location
<VirtualHost _default_:80>
ServerName localhost
DocumentRoot /Library/WebServer/Documents
</VirtualHost>
#
# PHP-FPM
#
LoadModule fastcgi_module $(brew --prefix mod_fastcgi)/libexec/mod_fastcgi.so
<IfModule fastcgi_module>
# Fake directory that handles php-fpm requests.
# Directory can be anything, it should not exist and will
# not be visible to the end-user
<Location "/fastcgiphp">
Order Deny,Allow
Deny from All
# Prevent accessing this path directly
Allow from env=REDIRECT_STATUS
</Location>
# Direct all PHP requests to the /fastcgiphp path
<FilesMatch \.php$>
SetHandler php5-fcgi
</FilesMatch>
Action php5-fcgi /fastcgiphp
Alias /fastcgiphp ${USERHOME}/Sites/php5-fpm
FastCgiExternalServer ${USERHOME}/Sites/php5-fpm -host 127.0.0.1:9000
# Allow index.php to be a DirectoryIndex
<IfModule dir_module>
DirectoryIndex index.html index.php
</IfModule>
</IfModule>
#
# VirtualHosts
#
## VirtualHost template
#<VirtualHost *:80>
# ServerName domain.local
# CustomLog "${USERHOME}/Sites/logs/domain.local-access_log" combined
# ErrorLog "${USERHOME}/Sites/logs/domain.local-error_log"
# DocumentRoot "${USERHOME}/Sites/domain.local"
#</VirtualHost>
#
# Automatic VirtualHosts
# A directory at ${USERHOME}/Sites/webroot can be accessed at http://webroot.dev
# In Drupal, uncomment the line with: RewriteBase /
#
# This log format will display the per-virtual-host as the first field followed by a typical log line
LogFormat "%V %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedmassvhost
<VirtualHost *:80>
ServerName dev
ServerAlias *.dev
CustomLog "${USERHOME}/Sites/logs/dev-access_log" combinedmassvhost
ErrorLog "${USERHOME}/Sites/logs/dev-error_log"
VirtualDocumentRoot ${USERHOME}/Sites/%-2+
</VirtualHost>
EOF
If you read that closely, you'll see that it's set up to do MassVirtualHosts using the *.dev
tld. For example, set up a web root at $HOME/Sites/project
and you will be able to view it at http://project.dev without needing to create a separate VirtualHost. A custom log format is used, putting the domain name at the beginning of the line, so you can easily see the output as it related to a project.
Restart Apache (if it was running) and set to start on boot:
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
There is no line with "RewriteBase /" to uncomment.
Can you add it in the right location