OS-X, NGINX, and Symfony2 – What a Party!

Google on OS-X, nginx, and Symfony2 and you’ll pull up a ton of posts. However I find them all confusing or missing pieces. Maybe I’m getting slow…maybe I’m not the command line guru…but in this post I will give you my take on how to setup these tools on OS-X Mavericks. Why? Well – I’m looking for speed and I suppose a challenge to wrack my brain with.

What is My Motivation?

I was serious – basically I’m looking for improvements on the ‘ol LAMP/OAMP stack. I have a program that is going to require some advanced processing power so I’m looking at how to scale better with PHP and web services. Apache has never been a great performer at scale. Most hosting companies have switched to nginx at the web tier for this reason. Since my personal machine is a MBP, I’ll be working with OS-X. I suppose for a server OS I would probably pick CentOS or something like that. I have VirtualBox installed so I could save myself some time and simply use that, but that’s no fun.

A note of caution: I am setting this up on my dev laptop, not a production server. Security is critical and I have not “battle tested” this configuration.

Where to get Started

Here’s the stuff we’re working with:

  • nginx
  • PHP
  • PHPFastCGI
  • Symfony2
  • HHVM – for the truly brave 🙂

There are a lot of references out there on the internet for how to do this, but I found them lacking. Here’s a few of the better posts that I used to piece all of this together:

That’s a lot of places to poke around, right? Right.

The first place to start is with OS-X. You’ll need to have XCode installed with the command line tools…probably means you need to be an active Apple developer. I’m going to rely on homebrew as a package manager so you’ll need that. To use homebrew you’ll need curl…here’s a good guide for how to get this setup.

The next step is to get PHP installed with the right stuff. We need to tap a couple of kegs (boy that sounds great, right?):

brew tap homebrew/dupes

brew tap josegonzalez/homebrew-php

Now we should have the package index we need. Tell brew to install PHP with the components we need:

brew install --without-apache --with-fpm --with-mysql php55

That will download and install everything you’ll need. Brew is pretty cool. What it did was download and install all the things you need in /usr/local/Cellar/ and then created the symlinks you need in /usr/lcoal/bin so that now your PHP environment is all ready to go. PHP should be installed in /usr/local/Cellar/php55. The .ini configuration files will be in /usr/local/etc/php/5.5 you can get to them via command line or with Finder using the “go to” option in Finder.

Part of the PHP install you just performed is FPM. To get it setup for autostart you need to add some things to your OS-X profile. The names below can vary depending on what exact version you have installed. At the time of writing I’ve installed 5.5.9 – if the file does not exist look in the Cellar and change out the name. The plist file should have references to FPM in it.:

mkdir -p ~/Library/LaunchAgents

cp /usr/local/Cellar/php55/5.5.9/homebrew-php.josegonzalez.php55.plist ~/Library/LaunchAgents/

Then you can start and stop the FPM server with:

launchctl load -w ~/Library/LaunchAgents/homebrew-php.josegonzalez.php55.plist

launchctl unload -w ~/Library/LaunchAgents/homebrew-php.josegonzalez.php55.plist

To see if the FPM server is running properly this command is helpful:

lsof -Pni4 | grep LISTEN | grep php

Installing MySQL

There are a variety of ways to get MySQL installed – including using brew, but I choose the easy solution of using the downloadable binary from the MySQL community. I also like the MySQLWorkBench for doing all my admin work. Its a decent GUI for OS-X actually – only beef I have is that it does not check for updates automatically. I’m not going to run through how to configure all security stuff – just know that you should do it.

To start/stop/restartMySQL use:

mysql.server start
mysql.server stop
mysql.server restart

Getting nginx Working

The first step – if you have apache httpd installed and running…turn it off…my instructions will use nginx on port 80. 🙂 For better security you could run it on some port like 9878. To run on 80 you need root/sudo rights. I will also not configure it with autostart because I will probably switch back and forth between nginx and apache. To install it is quite simple:

brew install nginx

The default doc root is /usr/local/var/www and the configuration files are in /usr/local/etc/nginx. There are a ton of ways to setup nginx. Checkout the first link above if you want to learn a ton for how to make working with it easy. What I did for my config was set it up to point at the same www root that apache does so that I can test development with both on the same code. To do that I modified the main config file with the following:

  1. I set the error logging directory to a folder in my home directory to make it easy to get to the logs.
  2. In the http section I did the same for the access logs.
  3. In the http section I changed the port to 80 and set the root directory to /Library/WebServer/Documents. I added index.php as an allowed type.
  4. I’m running FastCGI so I added this block in the http section:
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    root   /Library/WebServer/Documents;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
    }
  5. I added a section to deny access to .htaccess files (since they will be there because I’m sharing the directories with apache:
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
    deny  all;
    }

I didn’t bother to configure HTTPS yet. With all that done you should be able to start nginx with a simple command line:

sudo nginx

Pretty easy to stop and restart it as well

sudo nginx -s stop|restart

Throw a php file with the ‘ol info call in it and make sure it loads up.

Configuring OS-X, nginx, and Symfony2 with FPM

Installing Symfony2 is pretty well documented – so go ahead and get it installed (I recommend composer). One thing that can make it easier is to simply shut off nginx and start apache so that you can do the initial Symfony2 File LayoutSymfony2 install with confidence. After getting it installed you should be able to bring up the Symfony2 config page at localhost/yourApp/app_dev.php

You can see that I did something different. I have a single “master” composer file in the directory above so that all my S2 project share the same revs.

Also keep in mind that I am setting this to use /Library/WebServer/Documents as the www root. On OS-X this means I have to sudo all the changes. This can be a PITA, but it is also secure so just get used to being king of “sudo” or hack your box by messing with groups or whatever.

Once you have the basics working you can create a virtual server in nginx to make things work nice using a local entry in your hosts file. Go ahead and add s2.local as a 127.0.0.1 entry in your hosts file (on OS-X this is in /etc).

Now create two directories: sites-available and sites-enabled in /usr/local/etc/nginx. Add a file called s2.local, or whatever name you added to hosts file, to the sites-available directory. Add the following content to this file and save it:

#/usr/local/etc/nginx/sites-available/s2.local
server {
# Listen on port 80
listen 80;
# Server name being used (exact name, wildcards or regular expression)
server_name s2.local;
# Document root, make sure this points to your Symfony2 /web directory
root /Library/WebServer/Documents/s2-nginx/web;
index app_dev.php;
# Handle static files, redirect to app.php if not found
location / {
try_files $uri /app_dev.php$is_args$args;
}
# Pass the PHP scripts to FastCGI server
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass   127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param  HTTPS off;
}
# Logging
error_log /Users/beren/logs/s2.local-error.log;
access_log /Users/beren/logs/s2.local-access.log;
}

Now, symlink the s2.com file to the sites_enabled folder:
 sudo ln -s /usr/local/etc/nginx/sites-available/s2.com /usr/local/etc/nginx/sites-enabled/s2.com Symfony2 on Nginx
Restart FPM and nginx. Voila!

In the above I’m assuming that this is for a dev server. If you want this for production you need to modify the index from app_dev.php to just app_php and the location line in the same way.

With all this done you should be ready to go with Symfony2 development on PHP. You can keep on creating new apps and virtual servers like I did above add/remove them by removing the symlink. Pretty neat I think. I think it does take some getting used to with this setup, but once you get the hang of it, it is pretty nice.

Hopefully you found this helpful. I’ll keep coming back and adding more details over time along with any improvements I come up with. I’m working on getting Xdebug working with this using PHPStorm.

 

Leave a Reply