If you want to start developing PHP applications, or merely work on your PHP-based site off-line, on Mac OS X you can easily do so. In this how-to we'll see how you can set up NginX, a high performance web server, with the PHP version shipped with Mac OS X itself to create a local web server. In case you're wondering, you can of course use it in parallel with MAMP, XAMPP or even the multi-PHP version server I've described in an earlier post.
Install HomeBrew
If you don't have HomeBrew already you need to install it per its instructions. HomeBrew is a package manager for Mac OS X which lets you install a lot of software without hunting around the Internet for a suitable package file.
Install NginX
Open a Terminal window and enter the following command:
brew install nginx
After a couple of minutes it should tell you that the installation is complete. Now we need to create a few links to let us easily configure NginX and start it automatically.
You can configure NginX by editing the files inside the /usr/local/etc/nginx directory.
First, we need to edit the /etc/nginx/nginx.conf file because the default is a bit problematic. From a Terminal window type
sudo open /usr/local/etc/nginx/nginx.conf -a TextEdit
and replace the contents of the file with
user yourusername staff; worker_processes 1; error_log /var/log/nginx.error.log; error_log /var/log/nginx.error.log notice; error_log /var/log/nginx.error.log info; pid /var/tmp/nginx.pid; events { worker_connections 128; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log /var/log/nginx.access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 8080 default_server; listen [::]:8080 default_server ipv6only=on; server_name localhost; root /Users/yourusername/Sites; #access_log /var/log/nginx.localhost.access.log main; location / { index index.html index.htm index.php; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffers 256 128k; fastcgi_connect_timeout 300s; fastcgi_send_timeout 300s; fastcgi_read_timeout 300s; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one location ~ /\.ht { deny all; } } include servers/*; }
Change yourusername (shown in bold red letters) with your Mac OS X username. If you don't know what it is type the following in a Terminal window
whoami
The system will reply with your username.
At this point it should be noted that the web server root is set up to be the Sites folder inside your user's directory. If you are not sure whether you have this folder, type the following in a Terminal window
mkdir /Users/`whoami`/Sites
Starting, stopping and reloading NginX
We need to first tell Mac OS X to automatically start NginX whenever we boot the computer.
Please note that the 1.8.0 you see in the following instructions is the version number of NginX I installed at the time of this writing. Looks inside /usr/local/Cellar/nginx to see what is your actual version. Just open Finder, press ⇧⌘G type /usr/local/Cellar/nginx and press ⏎.
Assuming that the version is 1.8.0, you need to type the following into a Terminal window
sudo cp /usr/local/Cellar/nginx/1.8.0/homebrew.mxcl.nginx.plist /Library/LaunchAgents/ sudo chown root:wheel /Library/LaunchAgents/homebrew.mxcl.nginx.plist
The very first time you install NginX you need to start it manually. You can do that by typing the following into a Terminal window
sudo launchctl load -w /Library/LaunchAgents/homebrew.mxcl.nginx.plist
Stopping NginX requires typing the following into a Terminal window
sudo launchctl unload -w /Library/LaunchAgents/homebrew.mxcl.nginx.plist
You can restart it using the same command you used to start it the very first time.
After editing NginX' configuration, or the configuration of one of the server blocks (sites) you need to tell NginX to reload the configuration. You can do that by typing the following into a Terminal window
sudo nginx -s reload
Set up PHP-FPM
At this point your NginX server isn't very useful. It can only serve static content. We need to tell it how to run PHP scripts. Unlike Apache, there is no PHP module for NginX. Instead, it uses PHP-FPM (FastCGI Process Manager) which is just as fast and much more secure. We just need to enable it on your Mac. Type the following in a Terminal window
sudo mkdir -p /usr/share/php/var/log sudo mkdir -p /usr/share/php/var/run sudo touch /usr/share/php/var/run/php-fpm.pid sudo touch /usr/share/php/var/log/php-fpm.log sudo chmod 0777 /usr/share/php/var/run/php-fpm.pid sudo chmod 0777 /usr/share/php/var/log/php-fpm.log sudo cp /private/etc/php-fpm.conf.default /private/etc/php-fpm.conf sudo cp /etc/php.ini.default /etc/php.ini
You can edit /etc/php.ini to taste. Please note that since this is a system file you need to open it for editing from a Terminal window by typing
sudo open /etc/php.ini -a TextEdit
Now we need to edit the file /private/etc/php-fpm.conf and make some changes. Start by opening the file for editing by typing this to a Terminal window
sudo open /private/etc/php-fpm.conf -a TextEdit
Find the lines starting with pid = and error_log = and change them to
pid = /usr/share/php/var/run/php-fpm.pid error_log = /usr/share/php/var/log/php-fpm.log
Next up, find the user = and group = lines and change them to read
user = yourusername group = staff
Remember to change yourusername to your actual username, the same way you did for nginx.conf.
Finally, paste the following line at the bottom of the file
php_admin_value[session.save_path] = /usr/share/php/var/session
Now let's tell Mac OS X to load PHP-FPM automatically. From a Terminal window enter
sudo touch /Library/LaunchDaemons/net.php.php-fpm.plist
sudo open /Library/LaunchDaemons/net.php.php-fpm.plist -a TextEdit
Paste the following contents into this file:
<?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> <false/> <key>Label</key> <string>net.php.php-fpm</string> <key>ProgramArguments</key> <array> /usr/sbin/php-fpm <string>--fpm-config</string> <string>/private/etc/php-fpm.conf</string> </array> <key>RunAtLoad</key> <true/> <key>UserName</key> <string>root</string> <key>WorkingDirectory</key> /usr/share/php/fpm <key>StandardErrorPath</key> <string>/var/log/system.log</string> <key>ServiceDescription</key> PHP FastCGI Process Manager </dict> </plist>
Now launch PHP-FPM with the following Terminal command
sudo launchctl load -F /Library/LaunchDaemons/net.php.php-fpm.plist
You only need to do that the very first time. From now on PHP-FPM will auto-start on boot.
Testing it all works
Create a new file called phpinfo.php inside the Sites directory under your user directory. A simple way to do that:
touch /Users/`whoami`/Sites/phpinfo open /Users/`whoami`/Sites/phpinfo -a TextEdit
and enter the following contents:
<?php phpinfo();
Now visit this file from your browser at http://localhost:8080/phpinfo.php If all went according to the plan you should see a page stating the PHP version installed on your Mac along with its configuration info. Swell!
Creating server blocks (virtual hosts)
Doing development on subdirectories is very problematic if you intend to move your site into the domain's root later on. My personal favorite is creating one subdomain per site I'm working on locally using the non-existent local.web domain name to make sure I don't accidentally screw up a live site.
Let me show you how simple it is to create a new server block (virtual host) in NginX. In our example we'll create a new site which will be accessible under http://example.local.web:8080
First we need to create a new file with a .conf extension inside the /usr/local/etc/nginx/servers directory. There is no requirement for the file name but it's a good convention to use the site's subdomain and domain name. It will help you 5-6 months later when you won't remember what you've set up, why and how. So let's name our file example.local.web.conf. From a Terminal window:
touch /usr/local/etc/nginx/servers/example.local.web.conf open touch /usr/local/etc/nginx/servers/example.local.web.conf -a TextEdit
Paste the following contents into the file:
server { listen 8080; server_name example.local.web; server_name_in_redirect off; root /Users/yourusername/Sites/example; # Load an nginx.conf file in the site's root - FOR DEVELOPMENT ONLY! # IMPORTANT: If the file doesn't exist your server won't start! include /Users/yourusername/Sites/example/nginx.conf; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffers 256 128k; fastcgi_connect_timeout 300s; fastcgi_send_timeout 300s; fastcgi_read_timeout 300s; include fastcgi_params; } }
The things you need to change are:
- example.local.web. This is the name of your subdomain. It can be anything you want.
- yourusername. Replace it with your username as we already did when setting up NginX and PHP-FPM
- example. This is the subdirectory inside the Sites folder where the site files live, i.e. the site's root. The convention I use is that the directory name must be the same as the sudomain it's serving. Don't make yourself think!
The thing is that Mac OS X currently doesn't know that the domain example.local.web should be served by our local server. We can edit the file /etc/hosts and tell it so. From a Terminal window:
sudo open /etc/hosts -a TextEdit
Add the following line at the end of the file
127.0.0.1 example.local.web
Finally, we need to tell NginX to reload the configuration so it knows how to serve our site. From a Terminal window:
sudo nginx -s reload
That's it! You can now access your dev site from a browser typing http://example.local.web:8080/
Please note that it's best to close and re-open your browser, otherwise the browser thread may have not picked up the change in the /etc/hosts file and reply that the server was not found.
What if I don't like port 8080?
No problem at all. Just change the line
listen 8080;
in your NginX configuration files to reflect the port you want it to listen to. For example, to make it listen to the default HTTP port (which means that you can access the server as http://localhost instead of http://localhost:8080) change the line to
listen 80;
What about SEF URLs (Joomla!), permalinks (WordPress), routes (Drupal) and so on?
This is something you need to add to your server block files, i.e. the files inside the /usr/local/etc/nginx/servers directory. Typically it's something like this:
location / { try_files $uri $uri/ /index.php?$args; }
and MUST be placed BEFORE the location ~ .php$ line. That said it's best to consult the NginX and your site script's documentation for the "right way" to set it up for use with NginX. Some quick and useful links:
- Joomla!™ and NginX
- WordPress and NginX
- Drupal and NginX
- Magento and NginX
- PrestaShop and NginX
- phpBB3 and NginX
That's all folks! Enjoy your high performance local server!
I followed your steps but when I launched " launchctl load -F /Library/LaunchDaemons/net.php.php-fpm.plist " (I'm on root) I got the response: /Library/LaunchDaemons/net.php.php-fpm.plist: Invalid property list
FYI, # php-fpm -v already answers: PHP 5.5.27 (fpm-fcgi) (built: Jul 23 2015 00:22:14)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
And I'm on Yosemite OS X.
So what's wrong?
Thanks.
I had to fix the XML of the plist file like this: