Perfect PHP (and Lithium) Dev Environment Setup on OS X
But I digress. Today's post here is about how to setup the perfect web development environment on your Mac. In this case I'm going to be talking about PHP and the Lithium Framework. However, you could really be coding with Ruby or Python or whateve with pretty much this same setup.
I'd never recommend running a web server on Windows. So if you're on Windows you'll want to use a Linux VM...But, that leads to convenience issues with files between two operating systems. The same applies on OS X and when you use things like Vagrant you have the same problems. Not only that, but you're using WAY too many resources for something so simple. The only benefit to running a VM is that you can have several server configurations so you know that your VM mirrors your live server...But really, that's not as big of a deal as it sounds and keeping every VM image up to date quickly becomes a maintenance issue.
Native, native, native. You want everything to run on your main operating system natively. It's not as easy though because you have to compile a lot, there's no package manager like Linux...Oh...But there is! Enter Homebrew. I know many of you have heard of it, but for those who haven't...It's essentially a nice package manager for OS X. I like it better than the, older, MacPorts (port) too. For starters, you don't run anything as root. This leaves you with the ability to very easily remove things (or do over) and not get into any trouble with (seemingly) irreversible changes to your system.
So go to Homebrew's page and follow the instructions. Then you're going to want to get PHP 5.4. OS X comes with PHP 5 but it's dated. It's better than most shared web hosts you'll find out there, but it's still a little tiny bit dated. To get PHP 5.4 you'll want to use a different repository. Jose Gonzalez has a wicked good set of formulas / packages. Follow the instructions in the readme there on GitHub and you should be set in no time.
Yes, use PHP-FPM and copy the plist files so things launch on startup, etc.
Next, Nginx. I prefer Nginx over Apache because it has a much smaller footprint. The memory usage is super low. In fact, there's two processes on my machine right now (and always are) for nginx and one uses about 150Kb and the other 1.7Mb of RAM...And it kinda stays that way. Here is some more information on installing Nginx with brew, I believe it's already available if you just type brew install nginx...I don't think you need to "tap" anything (Linux equivelant of adding more repository sources).
I want to keep this a high level overview, if you're having trouble there is a wealth of information that you can find on Google with regard to setting up brew, nginx, php 5.4, php-fpm, etc. Get anything else you want by the way. MySQL, MongoDB, etc. PHP extensions too. Again, Gonzalez has a really awesome repository with many common PHP extensions. I personally use and recommend MongoDB so grab the PHP extension for that.
Another good idea may be to rename your /usr/bin/php and phpize and phar etc. files and symlink in the ones that brew installs. I recommend this as it is non-destructive on your original OS X system, but makes the entire machine use the new jam. You technically should then be able to install PHP modules with pecl and such (you will likely need some more dependencies, which are available from brew).
Now, you have PHP-FPM, Nginx, and PHP 5.4 at this point. Pretty basic. What makes this setup perfect?
The configuration of Nginx.
You'll want to add to the default conf that brew installs for Nginx, a line like so:
That will include additional configuration files. Unless you want to simply remove the nginx.conf default and replace it altogether with what I'm about to show you...That's fine too. Keep in mind you will need to comment out the entire server block in the default configuration anyway.
You'll want to ultimately use this configuration. Nginx is really awesome in how it can be configured. In this case it's essentially making a new subdomain/virtual host for each directory you have under /usr/local/sites (or wherever you want).
Got it? Great! Now each directory you add becomes available at dirname.dev.local in your browser! Well, soon. First you need to follow this port 80 forwarding trick. While you're at it, that's another good source for information about installing Nginx with brew. Then you need one final piece of software.
Dnsmasq is a super simple nameserver. I highly recommend it for development environments. It can be installed with brew quite easily. You'll want to setup in there a configuration like so:
That's it, aside from the default configuration. Simple! Now, all of those virtualhosts you setup will work...As soon as you update your network preferences to use your own machine as a DNS server. Go to System Preferences > Network > WiFi > Advanced > DNS. Write down your router's IP that's likely there. Add to the list 127.0.0.1 (it'll likely remove your router) and then add your router back. While you're at it, you may wish to add Google's free DNS which are 184.108.40.206 and 220.127.116.11. They are nice and fast. Drag and drop your 127.0.0.1 up to the top. This will use your nameserver, dnsmasq, first and if it doesn't have the info you need it'll go out to your router and/or Google, etc. Whatever else you have.
Now you're ready to rock. Of course, ensure you have all the services and databases that you need running. To create a new web site, simply create a directory under the /usr/loca/sites (or wherever you configured it to be) and under that directory another one named "www" and put your files in there. IF you have a Lithium Framework project and there's a "webroot" directory it will use that as the actual webroot for the virtual host. No need for .htaccess, etc. because we're using the hassle free Nginx.
This is how I have my OS X setup and it's a very very lightweight and efficient setup. I consider it to be perfect (for PHP and Lithium)...And it's simply amazing when I drag and drop one of the site folders over to CodeKit and have automatic updating of my open browser tabs when I make changes to project files as well as automatic less compiling and more.
One last note. Your PHP-FPM settings. They are likely out of control. If you open your System Monitor, you may see like 20 of them. That's not necessary. I get along just fine with about half a dozen or less. Afterall, they eat up a decent amount of RAM when there's 12 or 20 of them. Like 10-30MB each! That's easily several hundred megabytes of RAM you're using for no good reason. If you don't care, then fine...But I like to adjust things down a bit. Afterall, it's just me that's looking at the sites on my computer. I don't need to serve a ton of traffic.
Edit your php-fpm.conf file and look for "pm = dynamic" ... It is likely set to this. That's fine. It could also be static, but keep it dynamic. Below this you'll see things like "pm.max_children" and "pm.start_servers" etc. Lower these numbers. For the love of all that is holy, you do not need to start 20 processes to handle the load you will generate on your machine. I set my start_servers to 2, min_spare_servers to 2, max_children to 15, and max_servers to 5. Leave max_requests alone. You could adjust it if you wanted to keep starting and killing php-fpm processes...But you shouldn't have any sort of memory leaks.
Now you're cooking! You should have a total of no more than 200MB of RAM being used to power PHP and Nginx. MySQL, MongoDB, etc. they're all going to use additional RAM. You can tune MySQL a little bit, but MongoDB is going to use whatever the system lets it. Mine is currently using 26MB which isn't bad at all, but there's really not much in the database. This will increase over time...But you pretty much are running a very efficient setup here.