###Installing Apache 2.4 + PHP 5.6 + MySQL + SSL on Mac OS X Yosemite This is a TL;DR version of an upcoming blog entry for those who can read bash commands and scripts.
I prefer setting up the environment and leaving the original configuration files practically untouched. I only modify them to include my own files which include additional settings as well as overrides for the default ones. This way I have full control over the environment in just one folder.
I also like to work without the need to sudo
commands, so I set up Apache without access to privileged ports 80 and 443. Instead, I add port forwarding 80->8080
and 443->8443
.
By following this gist you will end up with the following folder structure:
~/workspace/
|_ environment/
|_ certificates/
|_ logs/
|_ my.cnf
|_ php.ini
|_ httpd.conf
NOTE: this setup is for a brand new (or re-installed) OS X Yosemite. If you know what you are doing, you might still have use of parts of this gist.
###Homebrew
# install homebrew
xcode-select --install
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
#verify
brew doctor
# tap required repos
brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php
brew tap homebrew/apache
brew update && brew upgrade
###Prepare
brew install git openssl wget zlib curl
# create folders and empty files
mkdir -p ~/workspace/environment/{tmp,logs,certificates}
touch ~/workspace/environment/httpd.conf
touch ~/workspace/environment/php.ini
touch ~/workspace/environment/my.cnf
touch ~/workspace/environment/tmp/local.dev.conf
touch ~/workspace/environment/tmp/index.html
touch ~/workspace/environment/tmp/info.php
# add to PATH
# replace '.bash_profile' with .zshrc or whatever shell config file you use
echo -e "\nexport PATH=\"/usr/local/sbin:$PATH\"" >> ~/.bash_profile
# set a better hostname than "Alexanders-MacBook-Pro"
# change 'alefi-mbp' to the hostname you wish to use for your machine
sudo scutil --set HostName alefi-mbp
###Apache 2.4 ####Install
# unload pre-installed apache
sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null
# install with brew
brew install httpd24 --with-brewed-openssl
ln -sfv $(brew --prefix httpd24)/homebrew.mxcl.httpd24.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist
At this point Apache should be up and running. Verify by visiting http://localhost:8080 and you should see It works!
.
####Forward ports Running the following will allow to run on port 80 and 443 without root privilege. The commands will add a port forwarding rule to OS X that will be applied on every login.
sudo bash -c 'export TAB=$'"'"'\t'"'"'
cat > /Library/LaunchDaemons/local.httpdfwd.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
${TAB}<key>Label</key>
${TAB}<string>co.echo.httpdfwd</string>
${TAB}<key>ProgramArguments</key>
${TAB}<array>
${TAB}${TAB}<string>sh</string>
${TAB}${TAB}<string>-c</string>
${TAB}${TAB}<string>echo "rdr pass proto tcp from any to any port {80,8080} -> 127.0.0.1 port 8080" | pfctl -a "com.apple/260.HttpFwdFirewall" -Ef - && echo "rdr pass proto tcp from any to any port {443,8443} -> 127.0.0.1 port 8443" | pfctl -a "com.apple/261.HttpFwdFirewall" -Ef - && sysctl -w net.inet.ip.forwarding=1</string>
${TAB}</array>
${TAB}<key>RunAtLoad</key>
${TAB}<true/>
${TAB}<key>UserName</key>
${TAB}<string>root</string>
</dict>
</plist>
EOF'
sudo launchctl load -Fw /Library/LaunchDaemons/local.httpdfwd.plist
Verify by visiting http://localhost:80.
####Configure Apache
# include our own conf file in apache main httpd.conf
echo -e "\n\nInclude $HOME/workspace/environment/httpd.conf" >> $(httpd -V|grep "SERVER_CONFIG_FILE"|awk '{print $2}'|tr -d \"\ |sed -n 's/SERVER_CONFIG_FILE=//p')
# point ServerRoot to ~/workspace for future conveniece
echo -e "ServerRoot $HOME/workspace\n\n" > ~/workspace/environment/httpd.conf
# restart apache
httpd -k restart
####Testing
This will set up a virtual host in ~/workspace/environment/tmp/
to validate Apache configuration.
echo -e "<h1>Hello world</h1>" > ~/workspace/environment/tmp/index.html
echo -e "Include environment/tmp/local.dev.conf\n\n" >> ~/workspace/environment/httpd.conf
cat > ~/workspace/environment/tmp/local.dev.conf <<EOF
<VirtualHost *:8080>
ServerName local.dev
DocumentRoot environment/tmp/
<Directory />
Require all granted
</Directory>
</VirtualHost>
EOF
httpd -k restart
Verify by visiting http://local.dev. You should see Hello world!
.
###PHP 5.6 ####Install
# install
brew install php56
ln -sfv $(brew --prefix php56)/homebrew.mxcl.php56.plist ~/Library/LaunchAgents
launchctl load -Fw ~/Library/LaunchAgents/homebrew.mxcl.php56.plist
# create the (sometimes) missing directory where php by default looks for
# additional configuration files
[[ ! -d $(php --ini|grep "Scan for"|awk -F": " '{print $2}') ]] && sudo mkdir -p $(php --ini|grep "Scan for"|awk -F": " '{print $2}')
sudo ln -s $HOME/workspace/environment/php.ini $(php --ini|grep "Scan for"|awk -F": " '{print $2}')/php.ini
# configure php in our own php.ini
cat > ~/workspace/environment/php.ini <<EOF
; Defines the default timezone used by the date functions
date.timezone = "$(sudo systemsetup -gettimezone|awk -F"\: " '{print $2}')"
; Maximum amount of memory a script may consume (default 128MB)
memory_limit = 512M
; Maximum size of POST data that PHP will accept. (0 to disable the limit)
post_max_size = 100M
; Maximum allowed size for uploaded files.
upload_max_filesize = 50M
; Default timeout for socket based streams (seconds)
default_socket_timeout =
; Maximum execution time of each script, in seconds
max_execution_time = 300
; Maximum amount of time in seconds each script may spend parsing request data.
max_input_time = 60
; Log errors to specified file.
error_log = $(dscl . -read /Users/`whoami` NFSHomeDirectory | awk -F"\: " '{print $2}')/environment/logs/php-error_log
EOF
# avoid future perl and pecl permissions problem
# https://github.com/Homebrew/homebrew-php/issues/1039#issuecomment-41307694
chmod -R ug+w $(brew --prefix php56)/lib/php
# enable opcache which is bundled with php 5.6 (not earlier!)
cat >> ~/workspace/environment/php.ini <<EOF
; Determines if Zend OPCache is enabled
opcache.enable=0
; The OPcache shared memory storage size.
opcache.memory_consumption=256
EOF
# enable php in apache
cat <(cat <<EOF
# PHP
LoadModule php5_module $(brew --prefix php56)/libexec/apache2/libphp5.so
AddHandler php5-script .php
AddType text/html .php
<IfModule dir_module>
DirectoryIndex index.php index.html
</IfModule>
EOF) ~/workspace/environment/httpd.conf > tmp.conf && mv tmp.conf ~/workspace/environment/httpd.conf
httpd -k restart
####Verify that PHP is working
echo -e "<?php phpinfo(); ?>" > ~/workspace/environment/tmp/info.php
Verify by visiting http://local.dev/info.php.
###Memcache (optional) ####Install
brew install memcached php56-memcache
ln -sfv $(brew --prefix memcached)/homebrew.mxcl.memcached.plist ~/Library/LaunchAgents
launchctl load -Fw ~/Library/LaunchAgents/homebrew.mxcl.memcached.plist
httpd -k restart
####Verify
echo -e "<?php echo memcache_connect('127.0.0.1', 11211) ? 'Memcache OK' : 'Memcache FAILED'; ?>" > ~/workspace/environment/tmp/info.php
Verify by visiting http://local.dev/info.php. You should see Memcache OK
.
###SSL
####Configure
Add SSL configuration to our ~/workspace/environment/httpd.conf
.
cat <(cat <<EOF
# SSL
LoadModule ssl_module libexec/mod_ssl.so
LoadModule rewrite_module libexec/mod_rewrite.so
Listen 8443
SSLCipherSuite HIGH:MEDIUM:\!aNULL:\!MD5
SSLPassPhraseDialog builtin
EOF) ~/workspace/environment/httpd.conf > tmp.conf && mv tmp.conf ~/workspace/environment/httpd.conf
####SSL caching
In order for SSL to work SSL caching must be enabled. This can be done either by using the default mod_socache_shmcb
or mod_socache_memcache
if you have installed Memcache in the previous part.
If Memcache is not installed:
cat <(cat <<EOF
# SSL caching
LoadModule socache_shmcb_module libexec/mod_socache_shmcb.so
SSLSessionCache "shmcb:/usr/local/var/run/apache2/ssl_scache(512000)"
SSLSessionCacheTimeout 300
EOF) ~/workspace/environment/httpd.conf > tmp.conf && mv tmp.conf ~/workspace/environment/httpd.conf
If Memcache is installed:
cat <(cat <<EOF
# SSL caching
LoadModule socache_memcache_module libexec/mod_socache_memcache.so
SSLSessionCache memcache:127.0.0.1:11211
SSLSessionCacheTimeout 300
EOF) ~/workspace/environment/httpd.conf > tmp.conf && mv tmp.conf ~/workspace/environment/httpd.conf
Now restart Apache:
httpd -k restart
####Add self-signed certificates See How to create a self-signed Certificate. These commands to the same, but without annoying prompts.
cd ~/workspace/environment/certificates
openssl genrsa -des3 -passout pass:x -out server.pass.key 1024
openssl rsa -passin pass:x -in server.pass.key -out server.key
rm server.pass.key
openssl req -new -key server.key -out server.csr -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
####Verify
# replace previous virtual host with SSL-enabled one and
# redirect traffic from HTTP to HTTPS
cat > ~/workspace/environment/tmp/local.dev.conf <<EOF
<VirtualHost *:8080>
RewriteEngine On
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]
</VirtualHost>
<VirtualHost *:8443>
ServerName local.dev
DocumentRoot environment/tmp/
<Directory />
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile environment/certificates/server.crt
SSLCertificateKeyFile environment/certificates/server.key
</VirtualHost>
EOF
httpd -k restart
Verify by visiting http://local.dev/php.info. You should get redirected to HTTPS URL and get prompted with a certificate warning which is normal with self-signed certificates.
For some reason Chrome is giving me random trouble at this step which I cannot yet pin-point. So if you have used Chrome up until now, try a different browser - FireFox works like a charm for me.
# install
brew install mysql
cp $(brew --prefix mysql)/support-files/my-default.cnf $(brew --prefix)/etc/my.cnf
# include our custom config file
echo -e "\n\n\!include $HOME/workspace/environment/my.cnf" >> $(brew --prefix)/etc/my.cnf
# configure mysql
cat > ~/workspace/environment/my.cnf <<EOF
[mysqld]
innodb_buffer_pool_size = 128M
max_allowed_packet = 1073741824
innodb_file_per_table = 1
EOF
# launch
ln -sfv $(brew --prefix mysql)/homebrew.mxcl.mysql.plist ~/Library/LaunchAgents/
launchctl load -Fw ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
# secure the mysql installation
$(brew --prefix mysql)/bin/mysql_secure_installation
###Wrap up
# remove testing files and virtual host
rm -rf ~/workspace/environment/tmp
sed -i '' '/local.dev.conf/d' ~/workspace/environment/httpd.conf
httpd -k restart
###Where to go from here? My project structure looks like this:
~/workspace/
|_ environment/
|_ certificates/
|_ logs/
|_ my.cnf
|_ php.ini
|_ httpd.conf
|_ projects
|_ 001-random-project
|_ _vhosts
|_ _logs
|_ htdocs
In my httpd.conf
I include projects/001-random-project/_vhosts/*.conf
. By having ServerRoot pointed at /Users/alexander/workspace
I can use relative paths in my Apache .conf
files.
Any configuration you need to do to Apache, PHP or MySQL may be done in the custom files in ~/workspace/environment/
.
###If things go very wrong The following commands will remove Apache, PHP, MySQL, Memcache and the port forwarding. Use your brain! For example, if you haven't installed Memcache, don't try to remove it.
Kudos to beeftornado for brew rmtree.
brew tap beeftornado/rmtree && brew install beeftornado/rmtree/brew-rmtree
sudo launchctl unload /Library/LaunchDaemons/local.httpdfwd.plist
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.memcached.plist
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.php56.plist
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist
unlink ~/Library/LaunchAgents/homebrew.mxcl.memcached.plist
unlink ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
unlink ~/Library/LaunchAgents/homebrew.mxcl.php56.plist
unlink ~/Library/LaunchAgents/homebrew.mxcl.httpd24.plist
brew rmtree httpd24
brew rmtree mysql
brew rmtree php56
brew rmtree memcached
brew rmtree php56-memcache
sudo rm /Library/LaunchDaemons/local.httpdfwd.plist
rm -rf $(brew --prefix)/etc/apache2
rm -rf $(brew --prefix)/etc/php
rm -rf $(brew --prefix)/etc/my.cnf
rm -rf /usr/local/var/mysql
Thanks for this!
Not sure why, but this was giving an error:
But this worked: