OS X

Installing a LAMP Stack and mcrypt on OS X Mavericks

I can install a LAMP stack in my sleep on Windows, but the process is considerably different on a Mac. For the record, I don’t like installing packages such as XAMPP/MAMP, because I like to have complete control over which versions of each component are installed. Also, I find it a good idea to know how to install each program individually, so you know how to set it up on a non-development server.

The following is going to be heavy on links and commentary.

First off, I installed xcode from the Mac App Store. I wanted it anyway for Objective-C testing, but also to install homebrew. (Clever url, that one.) I installed that because I am a definite fan of package management. After installing homebrew, I immediately ran a

$ brew update

so it was ready to go.

I started off with this guide. So, the Apache portion. Turns out that OS X ships with its own version of Apache. (As of writing, 2.2.26.) That was perfect for my purposes (Magento doesn’t support Apache 2.4.x). Apache is located in /etc/apache2, runs as the httpd process, and as the user _www.

The apache httpd conf is located at /etc/apache2/httpd.conf I changed the ServerName to

ServerName localhost:80

Apparently that gets rid of Apache warnings about not finding the fully qualified domain name. I also enabled the PHP module with

LoadModule php5_module libexec/apache2/libphp5.so

Now, I needed a vhost. The guide I was following, and others mentioned below, set up their vhost with a VirtualDocumentRoot, so it can change the document root based on the request url. For example, if I request folder123.dev, Apache can look for the files in folder123. For folder456.dev, it’ll look in folder456. So, I created a container for the document root in my home directory,

$ mkdir ~/Sites

I also created ~/Sites/sandbox/htdocs, giving ownership to the _www user, and making sure the group (staff) had write access.

$ sudo chown -R _www htdocs
$ sudo chmod -R g+w htdocs

Definitely remember the chmod portion or else you’ll be as confused as I was when you can’t download files into that directory.

The guides recommended creating a conf in the users directory at /etc/apache2/users/. However, I was curious how it was being included automatically. If you look at httpd.conf, you’ll see this under Supplemental Configuration.

# User home directories
Include /private/etc/apache2/extra/httpd-userdir.conf

If you open that file up, you’ll see the following lines.

#
# Users might not be in /Users/*/Sites, so use user-specific config files.
#
Include /private/etc/apache2/users/*.conf

So, I created my own dchan.conf and added these lines to it, changing /Users/username to my own home directory.


  ServerName dev
  DocumentRoot /Users/username/Sites
  VirtualDocumentRoot /Users/username/Sites/%-2/htdocs
  UseCanonicalName Off
 
  
    AllowOverride All
    Order allow,deny
    Allow from all
  

I restarted Apache using apachectl, and confirmed it was running.

$ sudo apachectl restart
$ ps aux | grep httpd

Next was PHP. PHP is also preinstalled, version 5.4.24 in my case. php.ini had to be created, fortunately there was already a template.

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

I enabled display_errors = On. Not much configuration to do at this time. I restarted Apache again.

The last part, MySQL. I had homebrew install it.

$ brew install mysql

I then unset the temp directory and initialized the MySQL data directory/system tables. whoami dynamically retrieves your current user account.

$ unset TMPDIR
$ mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp

I also wanted MySQL to run automatically upon system startup. Now, this was a new experience. It looks like there isn’t an equivalent to the “Services” GUI in OS X – there’s only launchctl. I thought that was somewhat at odds with the other user friendly aspects of the system, but I rolled with it. To add MySQL to the startup programs, I used these commands, from this guide:

$ mkdir -p ~/Library/LaunchAgents
$ ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

There are two types of services – Launch Agents and Launch Daemons. According to this,

“launch daemons can run without a user logged in. Launch daemons cannot display information using the GUI. Launch daemon configuration plist files are stored in the /System/Library/LaunchDaemons folder (for those provided by Apple et al) and /Library/LaunchDaemons (for the rest). Launch agents run on behalf of a user and therefore need the user to be logged in to run. Launch agents can display information through the window server. As with launch daemons, launch agent configuration plist files are stored in the /System/Library/LaunchAgents and /Library/LaunchAgents. User launch agents are installed in the ~/Library/LaunchAgents folder.”

Lastly, it was time to set a root password.

$ /usr/local/Cellar/mysql/5.6.19/bin/mysqladmin -u root -password 'PASSWORD HERE'

Then I manually started mysql.

$ mysql.server start

Now, one thing about connecting to MySQL – you can’t use the “localhost” string. I noticed the same issue in Windows 8 – I had to specifically use 127.0.0.1. There are two solutions to this, both documented here. One is just use 127.0.0.1, and the other is to create a symlink between /tmp/mysql.sock and /var/mysql/mysql.sock, linking whichever file is missing. I opted for the former solution, as it seemed less hacky.

Now that all the components are installed, I needed some DNS management. I could edit the /etc/hosts file, but I wanted to see if there was anything more elegant, and indeed there was.

There’s a utility called dnsmasq, conveniently available via homebrew.

$ brew install dnsmasq
$ sudo cp /usr/local/opt/dnsmasq/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons

I then created a conf file at /usr/local/etc/dnsmasq.conf. Like the other guides, I decided to go with a “.dev” wildcard domain for my folders, so my site would be available at sandbox.dev. (Apparently you can’t use the .local domain, because it’s reserved by OS X.)

# /usr/local/dnsmaq.conf
address=/.dev/127.0.0.1
rebind-domain-ok=/xip.io/nip.io/

I loaded it into launchctl.

$ sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

Now we need to connect dnsmasq to the OS DNS servers. Per this guide,

Navigate to System Preferences -> Network -> WiFi (or your most used network interface) Click Advanced, and go the DNS tab. Under DNS servers, add 127.0.0.1 at the top of the list, followed by 208.67.222.222 (or any other nameserver).

However, apparently you’ll have to do this for each wifi network you connect to. That sounded like a bit too much work, but this handy guide has two scripts that can take care of that.

There are two files you have to download.

Then I ran the following commands, per the above guide.

mv setdns.sh /usr/local/bin
chmod a+x /usr/local/bin/setdns.sh
sudo cp com.zizproductions.setdns.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/com.zizproductions.setdns.plist

Now going to http://sandbox.dev shows me the files I’ve placed in ~/Sites/sandbox/htdocs. Awesome.

At this point, I’m almost, but not quite ready to install Magento. I need mcrypt. This is something that was much easier on Windows, because all you have to do is uncomment a line to load in a precompiled .dll file. However, on OS X, there doesn’t seem to be any way around compiling the extension yourself.

Some sites have you download and compile libmcrypt, but per this site, our ever-handy homebrew, it can take care of that too.

$ brew install autoconf mcrypt

I downloaded the PHP source for my version. I extracted it and navigated to the ext/mycrypt folder. I then attempted to run /usr/bin/phpize, but here’s the output I received.

$ /usr/bin/phpize
grep: /usr/include/php/main/php.h: No such file or directory
grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
Configuring for:
PHP Api Version:        
Zend Module Api No:     

I knew this was incorrect because I compared that to the desired output here. Well, this stumped me for quite some time. I was in the correct directory, phpize existed, everything seemed to check out. Some posts mentioned that the xcode command line tools needed to be installed, and I thought they were because both xcode-select and gcc existed and returned output.

$ xcode-select -p
/Applications/Xcode.app/Contents/Developer

However, I found out it was not the case. I had to actually enter

$ xcode-select --install

and then say yes to the install dialog box. With that out of the way, phpize now returned the proper output.

$ /usr/bin/phpize
Configuring for:
PHP Api Version:         20100412
Zend Module Api No:      20100525
Zend Extension Api No:   220100525

Now to continue on.

$ ./configure
$ make
$ sudo make install

Now, I had to enable the newly compiled .so in /etc/php.ini. I added this line

extension=mcrypt.so

I restarted Apache for one last time

sudo apachectl restart

Finally, we’re in business. I installed Magento, remembering to enter 127.0.0.1 as the database host. And we’re off!

Leave a Reply

Your email address will not be published. Required fields are marked *