Install Nginx and PHP on OS X Mountain Lion (10.8)

Install Nginx and PHP on OS X Mountain Lion (10.8)

Nginx + PHP + OS X Mountain Lion = Love
Time Investment: 1.25 hours

The Skinny on Nginx

If you haven’t already heard of it, Nginx is a web server that has a reputation for extreme speed and efficiency. It has gained wide acceptance and usage amongst many people, including systems administrators who are responsible for the availability of high-traffic websites. Like Apache, Nginx’s basic function is to serve web content over HTTP and HTTPS. Also like Apache, Nginx can be configured to serve numerous other unique purposes such as load-balancing, etc. However, what sets Nginx apart from Apache is it’s performance under heavy loads. Nginx accomplishes this because it handles incoming requests using an event model while Apache uses a process model. Even under the heaviest loads, Nginx consumes only a fraction upon a fraction of the memory and CPU that Apache would to handle identical traffic profiles.

The Skinny on PHP-FPM

PHP-FPM stands for PHP – FastCGI Process Manager. It is an alternative PHP FastCGI implementation. PHP-FPM is faster and more efficient at serving PHP than alternatives such as mod_php in Apache (it should be noted that Apache can be configured to use PHP-FPM too). It can do this because it only has to worry about PHP when needed. In contrast, mod_php gets loaded for every request whether PHP is needed or not. Additionally, mod_php inherits all the other Apache modules needed to service the request. Beyond resource inefficiency, this has lifecycle implications too. PHP-FPM can terminate processes and pass results back as soon as it’s done with any PHP-level processing. mod_php must live out the entire process of the HTTP request which means Apache has to hang onto unused resources even if it doesn’t need them. This is a real killer on high traffic sites.

Our Focus: Nginx + PHP-FPM on OS X Mountain Lion (10.8)

Even if you use Nginx and PHP-FPM as an alternative to Apache/mod_php just in your development environment, you will probably notice an overall system performance gain. I did. This was especially true during heavy development when using tools such as Eclipse, Netbeans, XCode, etc.

In this article, I’ll focus on getting Nginx setup in an environment to support PHP-based application development. In the followup, we’ll focus on Python. This post is written from my notes and what I found to be true OS X Mountain Lion (10.8), however things are only slightly different for OS X Lion (10.7) and the difference mainly lies in the libpng library (at least it was the only one I experienced).

Assumptions

I am assuming you have a clean install of OS X Mountain Lion. If you already have some of the components necessary to get everything running you can simply skip and move on. If you already have Apache running, you can either turn it off in System Preferences or use launchctl to unload the corresponding launch/plist file. Also, I’m assuming you have TextMate installed as your preferred text editor. Use whatever editor makes you happy.

Install XCode 4.4

As of this writing, if you have access to OS X Mountain Lion, you are probably a member of Apple’s Mac Developer program or listed under a corporate account that affords you those privileges. At any rate, to make any of this happen on Mountain Lion, you will need XCode 4.4 (Developer Preview) in order to install the necessary Unix command line tools. I should also note that this is where you will experience a difference between Lion and Mountain Lion. Apple no longer distributes XCode as a package that installs all the Unix tools along with the installation of all the other XCode utilities and SDK’s. Instead, they have opted to distribute a software bundle which requires you to opt for installation of the Unix command line tools separately through a preferences option in XCode. To do this, open XCode and go to > “Preferences”. Click on the “Downloads” icon and select the components tab as shown in the figure below:

Installling Unix Command Line Tools via XCode 4.4

Install XQuartz

To compile PHP successfully, you will need libpng. The easiest way to solve this dependency is to use the libraries that are included in the X11/XQuartz distribution. To install XQuartz, go to: http://xquartz.macosforge.org/trac/wiki/X112.7.0.

Download the latest version and install it.

Install Homebrew

I use Homebrew to manage some of my packages and dependencies. I prefer Homebrew as an alternative to Fink or MacPorts because I like how it stays out of your way and is highly flexible when you do want to use it. If you don’t want to use or install Homebrew, you will need to make sure you install libjpeg, mcrypt and mysql whichever way you feel comfortable. If you want to use Homebrew, roll on:

/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

Install libjpeg and mcrypt using Homebrew

To compile PHP, you will need libjpeg, libpng and mcrypt. Because we are on OS X, we will address libpng separatley. For now, install libjpeg and mcrypt using Homebrew:

brew install libjpeg mcrypt

Creating a work area

When you download and install packages or libraries from source, it’s good to keep them consolidated in one place. I like to use the same location as I do on our Linux and FreeBSD servers so /usr/local/src it is. Go ahead and issue the following command in your console to create that location if it doesn’t exist already:

mkdir -p /usr/local/src

Install PCRE

With PCRE, we are going to download and compile it ourselves. When you install PCRE, make sure you install the current stable release (8.21 as of this writing). Do not attempt to use 8.3. You will encounter problems compiling PHP later if you do. Below are the steps to download, compile and install PCRE 8.21:

cd /usr/local/src
curl -O ftp : //ftp .csx.cam.ac.uk /pub/software/programming/pcre/pcre-8 .21. tar .gz
tar xzvf pcre-8.21. tar .gz
cd pcre-8.21
. /configure
-- enable -unicode-properties
-- enable -utf8
make
sudo make install

Install ICU libs

Another dependency is the ICU libs. Below are the steps to download, compile and install icu:

mdkdir /usr/local/src
curl -O http: //download .icu-project.org /files/icu4c/4 .8.1.1 /icu4c-4_8_1_1-src .tgz
tar -xzf icu4c-4_8_1_1-src.tgz
cd icu
sh source /configure --prefix= /usr/local
gnumake
sudo make install

Compile IMAP libraries for PHP

One last major dependency we need to address are the IMAP libs. In this case, we will not be installing them. We will just compile them and create some symbolic links so the compiler can use them when it compiles PHP. To do this, follow these steps:

cd /usr/local/src
curl -O ftp : //ftp .cac.washington.edu /imap/imap . tar .Z
tar xzvf imap. tar .Z
cd imap-2007f
make osx
ln -s c-client include
mkdir lib
cd lib
ln -s .. /c-client/c-client .a libc-client.a

Installing MySQL using Homebrew

Finally, with all that out of the way, we can worry about MySQL. In this case, I use Homebrew (mainly because I’m lazy and they auto-generate a plist file I can use easily). Hey, if I can save 5 – 10 minutes, why not? Below are the steps to install MySQL using Homebrew:

brew install mysql
unset TMPDIR
mysql_install_db --verbose --user=` whoami ` --basedir= "$(brew --prefix mysql)" --datadir= /usr/local/var/mysql --tmpdir= /tmp
mkdir -p ~ /Library/LaunchAgents
cp /usr/local/Cellar/mysql/5 .5.19 /homebrew .mxcl.mysql.plist ~ /Library/LaunchAgents/
launchctl load -w ~ /Library/LaunchAgents/homebrew .mxcl.mysql.plist
/usr/local/Cellar/mysql/5 .5.19 /bin/mysql_secure_installation

Compile and install PHP

Before we go any further, OS X Mountain Lion ships with php 5.3.8. If you want to use the default version of php and php-fpm, you can do so by skipping this step and proceeding to configuring PHP-FPM as a LaunchDaemon. PHP-FPM lives in /usr/sbin. You can use the exact same plist file that is specified in the next step. If you want to compile and install php 5.3.10, follow the steps below:

cd /usr/local/src
curl -O http: //us2 .php.net /distributions/php-5 .3.10. tar .bz2
tar xzvf php-5.3.10. tar .bz2
cd php-5.3.10
. /configure --prefix= /usr/local
--mandir= /usr/share/man
--infodir= /usr/share/info
--sysconfdir= /private/etc
-- enable -cli
--with-config- file -path= /usr/local/php/etc
--with-libxml- dir = /usr
-- enable -xml
-- enable -exif
-- enable - ftp
-- enable -intl
--with-gd
--with-jpeg- dir = /usr/local/Cellar/jpeg/8c/lib
--with-png- dir = /usr/X11
-- enable -gd-native-ttf
--with-imap= /usr/local/src/imap-2007f
--with-imap-ssl
-- enable -magic-quotes
-- enable -mbstring
-- enable -mbregex
-- enable -json
--with-mysql=mysqlnd
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--with-mysql-sock= /tmp/mysql .sock
--with-iodbc= /usr
-- enable -shmop
--with-snmp= /usr
-- enable -sockets
-- enable -fpm
--with-mhash
--with-mcrypt
--with-xmlrpc
-- enable -xmlwriter
-- enable -xmlreader
--with-xsl= /usr
-- enable -zend-multibyte
-- enable -zip
--with-pcre-regex= /usr/local
--with-pdo-sqlite
-- enable -pdo
--with-pdo-mysql
--with-freetype- dir = /usr/X11
-- enable -dom
-- enable -fileinfo
 
make
sudo make install

At this point PHP is installed. However, the php distribution that shipped with OS X is still in /usr/bin which is in your system path first. An easy way to activate your new installation is to move the old binaries by renaming them andcreate symlinks in /usr/bin and /usr/sbin that point to the binaries that were compiled. Using this method, you can easily revert back to the original binaries that shipped by simply deleting the symlinks. You can complete that process like this:

sudo cp /private/etc/php-fpm .conf.default /private/etc/php-fpm .conf
sudo mkdir /usr/local/php/etc
sudo cp /private/etc/php .ini.default /usr/local/php/etc/php .ini
sudo ln -s php.dSYM php
sudo ln -s php-fpm.dSYM php-fpm
sudo mv /usr/bin/php /usr/bin/php .old
sudo ln -s /usr/local/php/bin/php /usr/bin/php
sudo mv /usr/bin/phpize /usr/bin/phpize .old
sudo ln -s /usr/local/php/bin/phpize /usr/bin/phpize
sudo mv /usr/bin/php-config /usr/bin/php-config .old
sudo ln -s /usr/local/php/bin/php-config /usr/bin/php-config
sudo mv /usr/sbin/php-fpm /usr/sbin/php-fpm .old
sudo ln -s /usr/local/php/sbin/php-fpm /usr/sbin/php-fpm

Configure launchd to start php-fpm during boot

Part of the power of PHP-FPM is the level of granularity in which you can manage your configurations. Because it allows you to configure pools differently, you can think of PHP-FPM much like an application server with each pool configured and tweaked for a specific purpose. We will setup PHP-FPM to look for pool configurations in /usr/local/php/fpm/pool.d. If you need to configure pools differently for different applications, you can create multiple unique configurations in this sub-directory. PHP-FPM will load them and you can configure Nginx to hand it’s process off upstream to the proper pool. Since we are using a Unix based OS, we are going to configure php-fpm to listen on a Unix socket to squeeze out extra performance. Alternatively, you can also use TCP in situations where Unix sockets aren’t an option. You can also configure PHP-FPM to listen on both at the same time. To get this all setup, we must first make two directories: 1) /usr/local/php/var/run and 2) /usr/local/php/fpm/pool.d.

/usr/local/php/var/run is where the pid file will be stored while the php-fpm daemon is running and as mentioned above, /usr/local/php/fpm/pool.d is where the pool configurations will reside. Let’s make those directories now:

mkdir -p /usr/local/php/var/run
mkdir -p /usr/local/php/fpm/pool .d

After you have created the directories, we need to make a basic config file for PHP-FPM. The master config file will reside at: /private/etc/php-fpm.conf. Let’s create the file:

mate /private/etc/php-fpm .conf

Now, paste the following into php-fpm.conf and save:

1
2
3
4
5
6
7
8
9
10
11
;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;
 
[global]
pid = /usr/local/php/var/run/php-fpm.pid
; run in background or in foreground?
; set daemonize = no for debugging
daemonize = yes
 
include=/usr/local/php/fpm/pool.d/*.conf

Notice the last line: include=/usr/local/php/fpm/pool.d/*.conf. We need to make sure to place at least one pool configuration file there so PHP-FPM will configure one pool when it starts.

mate /usr/local/php/fpm/pool .d /pool .conf

Now, paste the following text into pool.conf and save:

1
2
3
4
5
6
7
8
9
10
11
12
[www]
user=(REPLACE WITH YOUR USER NAME)
group=staff
pm = dynamic
pm.max_children = 10
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
listen = /tmp/php-fpm.sock
;listen = 127.0.0.1:9000
php_flag[display_errors] = off

The last thing in our lineup for getting PHP-FPM setup is to make sure it starts up every time the system restarts. Just create a new plist file for the LaunchDaemon:

mate /Library/LaunchDaemons/net .php.php-fpm.plist

Now, copy the following code into TextMate and save the net.php-fpm.plist file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<? 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 >
     < key >KeepAlive</ key >
     < true />
     < key >Label</ key >
     < string >net.php.php-fpm</ string >
     < key >LaunchOnlyOnce</ key >
     < true />
     < key >NetworkState</ key >
     < true />
     < key >ProgramArguments</ key >
     < array >
         < string >/usr/sbin/php-fpm</ string >
     </ array >
     < key >RunAtLoad</ key >
     < true />
     < key >ServiceDescription</ key >
     < string >PHP FastCGI Process Manager</ string >
     < key >StandardErrorPath</ key >
     < string >/var/log/system.log</ string >
</ dict >
</ plist >

Once the file has been saved, make sure you load it:

sudo launchctl load -F /Library/LaunchDaemons/net .php.php-fpm.plist

For a quick sanity check, go ahead and issue the following command to make sure the php-fpm process is running:

ps aux | grep php-fpm

You should see output similar to the output below:

your_username        91743   0.0  0.0  2432764    600 s000  R+   11:56PM   0:00.00 grep php-fpm
your_username        91730   0.0  0.0  2454736    480   ??  S    11:55PM   0:00.00 /usr/sbin/php-fpm
your_username        91729   0.0  0.0  2454736    480   ??  S    11:55PM   0:00.00 /usr/sbin/php-fpm
your_username        91728   0.0  0.0  2454736    480   ??  S    11:55PM   0:00.00 /usr/sbin/php-fpm
your_username        91727   0.0  0.0  2454736    480   ??  S    11:55PM   0:00.00 /usr/sbin/php-fpm
your_username        91726   0.0  0.0  2454736    476   ??  S    11:55PM   0:00.00 /usr/sbin/php-fpm
root                 91725   0.0  0.0  2454736    720   ??  Ss   11:55PM   0:00.01 /usr/sbin/php-fpm

Also, just to be sure, let’s check that PHP-FPM is listening on a Unix socket:

netstat -n -a | grep php-fpm

You should see output similar to the output below:

ffffff801bb62ce8 stream      0      0 ffffff8023afd078                0                0                0 /tmp/php-fpm .sock

Compiling and Installing Nginx

Installing Nginx is fairly straightforward. You can either download and compile it yourself, or you can choose to use Homebrew. In this case, I prefer compiling it myself.

curl -O http: //nginx .org /download/nginx-1 .1.16. tar .gz
tar xzvf nginx-1.1.16. tar .gz
cd nginx-1.1.16
. /configure
     --sbin-path= /usr/local/sbin/nginx
     --conf-path= /usr/local/nginx/nginx .conf
     --with-http_ssl_module
     --with-pcre=.. /pcre-8 .30
make
make install

Setting Yourself Up For Success With Nginx Configuration

I like to setup Nginx’s configuration structure similar to the way Ubuntu handles both Apache and Nginx to help streamline and decouple the different configurations. I have a master nginx.conf file that pulls in other configuration components as necessary. For site configurations, I create two directories under /usr/local/etc/nginx called sites-enabled and sites-available. The sites-available directory contains one to many configuration files, each representing one virtual host configuration. The sites-enabled directory contains symbolic links to the files in the sites-available directory. When nginx.conf is loaded it will in turn load all the symlinked files in the sites-enabled directory for active configurations when it starts up. Using this approach, you can turn off a virtual host by simply removing the symlink.

Create the directories:

mkdir /usr/local/nginx/sites-enabled
mkdir /usr/local/nginx/sites-available

Open the existing nginx.conf file:

mate /usr/local/nginx/nginx .conf

Replace the entire contents of the current nginx.conf file with the following contents:
nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
worker_processes 2 ;
 
events {
    worker_connections 1024 ;
}
 
http {
    include mime.types;
    default_type text/plain;
    server_tokens off;
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 1 ;
    gzip on;
    gzip_comp_level 2 ;
    gzip_proxied any;
    gzip_types text/plain text/css text/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;
 
    index index.html index.php;
 
    upstream www-upstream-pool{
       server unix: /tmp/php-fpm.sock;
    }
 
   include sites-enabled/*.dev;
}

The “upstream” directive in the code above provides Nginx a mapping to an upstream process that we can refer to later when we want to pass fastcgi requests. In this manner, you could easily create and configure multiple upstreams and delegate to them as needed on a per app basis or even on a per URI basis if you wanted to break your application down into logical groups of functionality that required different resource configurations. Pretty simple! Now, we just need to make sure we create a default configuration file for hosts to load that need to support php and requests upstream to PHP-FPM:

mate /usr/local/nginx/fastcgi_php_default .conf

Copy and paste the following code into fastcgi_php_default.conf ans save:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
fastcgi_intercept_errors on;
 
location ~ .php$
{
     fastcgi_split_path_info ^(.+.php)(/.+)$;
 
     fastcgi_param  SCRIPT_FILENAME    $document_root $fastcgi_script_name ;
     fastcgi_param  QUERY_STRING       $query_string ;
     fastcgi_param  REQUEST_METHOD     $request_method ;
     fastcgi_param  CONTENT_TYPE       $content_type ;
     fastcgi_param  CONTENT_LENGTH     $content_length ;
 
     fastcgi_param  SCRIPT_NAME        $fastcgi_script_name ;
     fastcgi_param  REQUEST_URI        $request_uri ;
     fastcgi_param  DOCUMENT_URI       $document_uri ;
     fastcgi_param  DOCUMENT_ROOT      $document_root ;
     fastcgi_param  SERVER_PROTOCOL    $server_protocol ;
     fastcgi_param  HTTPS              $https if_not_empty;
 
     fastcgi_param  GATEWAY_INTERFACE  CGI / 1 . 1 ;
     fastcgi_param  SERVER_SOFTWARE    nginx/ $nginx_version ;
 
     fastcgi_param  REMOTE_ADDR        $remote_addr ;
     fastcgi_param  REMOTE_PORT        $remote_port ;
     fastcgi_param  SERVER_ADDR        $server_addr ;
     fastcgi_param  SERVER_PORT        $server_port ;
     fastcgi_param  SERVER_NAME        $server_name ;
 
     fastcgi_param PATH_INFO         $fastcgi_path_info ;
     fastcgi_param PATH_TRANSLATED   $document_root $fastcgi_path_info ;
 
     fastcgi_read_timeout 300 ;
 
     fastcgi_pass www-upstream-pool;
 
     fastcgi_index index.php;
}
 
fastcgi_param  REDIRECT_STATUS    200 ;

The next thing we need to accomplish is setting up a test host. We will need to create a document root for the site files and then a configuration file for Nginx to load. On my machine, I keep all my projects in a “Repo” folder in my home directory. I’m going to setup a document root for “mytestsite.dev” under the Repo folder and create an index.php file for the test site:

mkdir -p ~ /Repo/mytestsite .dev
echo "<?php phpinfo(); ?>" >> ~ /Repo/mytestsite .dev /index .php

Now, let’s create the host configuration file for Nginx:

mate /usr/local/nginx/sites-available/mytestsite .dev

Paste the following configuration into mytestsite.dev and save:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
    listen 80 ;
    server_name mytestsite.dev;
    root ~/Repo/mytestsite;
    access_log logs/access_mytestsite.log;
    error_log logs/error_mytestsite.log;
 
    location / {
       index index.php;
       try_files $uri $uri / /index.php?q= $uri & $args ;
    }
 
    include fastcgi_php_default.conf;
}

Now, create the plist to add Nginx as a LaunchDaemon:

mate /Library/LaunchDaemons/net .nginx.nginx.plist

Paste this into the editor and save it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<? 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 >
     < key >Label</ key >
     < string >net.nginx.nginx</ string >
     < key >RunAtLoad</ key >
     < true />
     < key >KeepAlive</ key >
     < true />
     < key >ProgramArguments</ key >
     < array >
         < string >/usr/local/sbin/nginx</ string >
         < string >-g</ string >
         < string >daemon off;</ string >
     </ array >
     < key >WorkingDirectory</ key >
     < string >/usr/local</ string >
   </ dict >
</ plist >

Just ike mysql and php-fpm, load the plist so that launchd starts up Nginx every time you reboot:

sudo launchctl load -F /Library/LaunchDaemons/net .nginx.nginx.plist

Setup Your Hosts File

The last step in the process is to create a record in your hosts file that points “mytestsite.dev” to your localhost. It’s simple:

sudo mate /etc/hosts

Now, add a line and save the hosts file:

127.0.0.1   mytestsite.dev

Again, let’s do a quick test by trying to ping the host:

ping -t 4 mytestsite.dev

You should see a response like this:

Ping response.

Ok, now let’s fire up a browser and go to http://mytestsite.dev and you should see:

phpinfo index page on the mytestsite.dev.

Final Thoughts

That should do it. You should be ready to roll and have a dev environment on your Mac using Nginx as the primary web server.


转自:http://www.group7even.com/blog/2012/02/23/installing-nginx-php-fpm-on-os-x-mountain-lion-10-8/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值