Install Nginx & PHP with FastCGI & MySQL on OSX 10.7
Here we go, after months of standby a new post that I think can be useful for some of you wanting to install nginx (http server) and compile PHP with fastcgi (you have to run PHP as a CGI with nginx).
So first why nginx? You can find the answer here or here.
Now, to install our server we first need to install homebrew. For those who don’t know homebrew it’s like macports but faster. I personally use homebrew after having trouble with macports.
1. Install homebrew
So to install homebrew, first you need Xcode for Lion that you can download here, it’s free.
You also need Java installed.
Once you’ve installed those components (it will take a while, I think xCode is something like 3.5GB to download, don’t forget to install xCode after downloading it) you have to install homebrew , opening a terminal a typing the following command (we’ll use the terminal from now):
$ sudo /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"
Once homebrew is install we’ll use it to install wget to download all the packages we need
$ brew install wget
2. Install Nginx
$ brew install nginx $ cp /usr/local/Cellar/nginx/1.0.6/org.nginx.nginx.plist ~/Library/LaunchAgents/ $ launchctl load -w ~/Library/LaunchAgents/org.nginx.nginx.plist $ vi /usr/local/etc/nginx/nginx.conf
Search for “8080″ and replace it by “80″, save and exit (:wq)
3. Install MySQL
http://dev.mysql.com/downloads/mysql/
$ cd /usr/local $ mkdir src $ cd src $ wget http://mysql.mirrors.ilisys.com.au/Downloads/MySQL-5.5/mysql-5.5.16-osx10.6-x86_64.tar.gz $ tar -xzf mysql-5.5.16-osx10.6-x86_64.tar.gz
Once you’ve done that you can create a mysql folder and copy the source in it:
$ mkdir /usr/local/mysql $ cd /usr/local/mysql $ cp -R /usr/local/src/mysql-5.5.16-osx10.6-x86_64/* ./
Now you have to create the basic tables for the server:
$ cd /usr/local/mysql $ sudo ./scripts/mysql_install_db --user=mysql
Wait for a little while, time for the server to create all the table, open the socket, etc…
$ cd /usr/local/mysql $ sudo ./bin/mysqld_safe & $ ps -ef | grep mysql $ cd /usr/local/src $ vi com.mysql.server.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.mysql.server</string>
<key>KeepAlive</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/mysql/bin/mysqld_safe</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
$ cp com.mysql.server.plist ~/Library/LaunchAgents/ $ launchctl load -w ~/Library/LaunchAgents/com.mysql.server.plist
You should see mysql running in the processes. Now will create a symlink to the mysql socket
$ mkdir /var/mysql $ sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock
Now we set the admin password for mysql
$ cd /usr/local/mysql $ sudo ./bin/mysqladmin -u root password 'mycomplexpassword'
And done! mysql is installed…
4. Download & Compile PHP 5.3.8
Here I had a couple of issues that I can share with you. First the hardware configuration I have is a Macbook Pro from late 2009, it’s a dual core so I will install php x86_64.
What you need to do is to download the source here.
$ cd /usr/local/src $ wget http://au.php.net/distributions/php-5.3.8.tar.gz $ tar -xzf php-5.3.8.tar.gz
This is done we need to configure the installation. What you ned to do first is to set some variables that will indicate that you want to install the 64bit version of PHP.
$ MACOSX_DEPLOYMENT_TARGET=10.7 $ CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp" $ CCFLAGS="-arch x86_64 -g -Os -pipe" $ CXXFLAGS="-arch x86_64 -g -Os -pipe" $ LDFLAGS="-arch x86_64 -bind_at_load" $ export CFLAGS CXXFLAGS LDFLAGS CCFLAGS MACOSX_DEPLOYMENT_TARGET
We are done with that, now we need to configurate the options for PHP. We are going to install PHP with the support for gd so we need to install few libs before to do so. The first lib is jpeg, we’ll also need libxml2 and iconv.
$ brew install jpeg $ brew install libxml2 $ brew install libiconv
Here we go we are ready… Let’s configure the installation:
./configure \ --prefix=/usr/local \ --with-ldap=/usr \ --enable-cli \ --with-zlib-dir=/usr \ --enable-exif \ --enable-ftp \ --enable-mbstring \ --enable-mbregex \ --enable-sockets \ --with-iodbc=/usr \ --with-curl=/usr \ --with-config-file-path=/etc \ --with-mysql-sock=/var/mysql \ --with-mysqli=/usr/local/mysql/bin/mysql_config \ --with-mysql=/usr/local/mysql \ --with-openssl=/usr \ --with-xmlrpc \ --with-xsl=/usr \ --with-libxml-dir=/usr \ --with-iconv=/usr/local \ --with-pdo-mysql=/usr/local/mysql/bin/mysql_config \ --with-gd \ --with-jpeg-dir=/opt/local \ --with-png-dir=/usr/X11 \ --with-freetype-dir=/usr/X11 \ --with-mcrypt=/usr/X11
As libpng and freetype are already install by default you need to specify the OSX dir for those one. Now we need to modify the Makefile file from the php source folder.
$ vi Makefile
You need to change this line:
$(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ && cp $@ libs/libphp$(PHP_MAJOR_VERSION).so
By this one:
$(CC) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) $(MH_BUNDLE_FLAGS) -o $@ && cp $@ libs/libphp$(PHP_MAJOR_VERSION).so
You need to add -lresolv to the EXTRA_LIBS:
EXTRA_LIBS = -lexslt -liodbc -lmysqlclient -lmcrypt -lltdl -lldap -llber -liconv -liconv -lfreetype -lpng -lz -ljpeg -lcrypto -lssl -lcrypto -lcurl -lz -lcrypto -lssl -lcrypto -lm -lxml2 -lz -licucore -lm -lcurl -lxml2 -lz -licucore -lm -lmysqlclient -liodbc -lmysqlclient -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxslt -lxml2 -lz -licucore -lm -lresolv
Save and close the file (:wq)
Before do continue we also need to change the path of the mysql lib which is pointing to a wrong place at the moment. To do so:
$ sudo install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/local/src/php-5.3.8/sapi/cli/php
Now we can do:
$ sudo make $ sudo make install
And done! PHP is installed
If you get the following errors: configure: error: png.h not found. You need to specify the png dir with the option "--with-png-dir=/usr/X11", make sure you specify /usr/X11 and not /usr/X11/lib, cf. here dyld: Library not loaded: libmysqlclient.18.dylib You need to change the path of the mysql lib, like the following Undefined symbols for architecture x86_64: "_res_9_init", referenced from: You need to add -lresolv to the EXTRA_LIBS, like here.
If you go in /usr/local/bin/ you should see 2 files: php-cgi.dSYM and php.dSYM
If you want to know why there is this extension on the file, it’s here.
you need to rename it as followed:
$ mv /usr/local/bin/php-cgi.dSYM /usr/local/bin/php-cgi $ mv /usr/local/bin/php.dSYM /usr/local/bin/php
Then you need to correct the library path in php-cgi:
$ sudo install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/local/bin/php-cgi
Create the plist file to start php-cgi at startup
$ vi ~/Library/LaunchAgents/com.phpfcgi.plist
<?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>Debug</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>PHP_FCGI_CHILDREN</key>
<string>2</string>
<key>PHP_FCGI_MAX_REQUESTS</key>
<string>1000</string>
</dict>
<key>Label</key>
<string>com.phpfcgi</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/php-cgi</string>
<string>-b127.0.0.1:9000</string>
<string>-q</string>
</array>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>
And load the plist
$ launchctl load -w ~/Library/LaunchAgents/com.phpfcgi.plist
Well I think I’ve covered most of the issue that you can encountered while compiling PHP. If you have more issue or if you want to add something to the process feel free to post a comment.
5. Configure Nginx with VirtualHosts
First you need to add the domain you want to use in the hosts file
$ sudo vi /private/etc/hosts
... 127.0.0.1 localhost 127.0.0.1 myfirstdomain.local 127.0.0.1 myseconddomain.local ...
Then you need to flush the cache of the DNS
$ sudo dscacheutil -flushcache
Create the log folder and edit nginx.conf
$ sudo mkdir -p /usr/local/var/log/nginx/ $ vi /usr/local/etc/nginx/nginx.conf
worker_processes 1;
error_log /usr/local/var/log/nginx/error.log info;
pid /usr/local/var/run/nginx.pid;
events {
worker_connections 256;
}
http {
include mime.types;
default_type application/octet-stream;
access_log /usr/local/var/log/nginx/access.log;
sendfile on;
keepalive_timeout 65;
gzip on;
# HTTP server
include /usr/local/etc/nginx/vhosts.conf;
}
Now we create the vhost file:
$ mkdir -p /usr/local/share/nginx/html/myfirstdomain/www $ mkdir -p /usr/local/share/nginx/html/myseconddomain/www $ vi /usr/local/etc/nginx/vhosts.conf
server {
listen 8080;
server_name myfirstdomain.local;
root /usr/local/share/nginx/html/myfirstdomain/www;
index index.html index.htm index.php;
access_log /usr/local/var/log/nginx/myfirstdomain.access.log;
#error_page 404 /404.html;
location ~ html|css|js|jpg|png$ {
try_files $uri index.php
break;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/share/nginx/html;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /usr/local/etc/nginx/fastcgi.conf;
break;
}
}
server {
listen 8080;
server_name myseconddomain.local;
root /usr/local/share/nginx/html/myseconddomain/www;
index index.html index.htm index.php;
access_log /usr/local/var/log/nginx/myseconddomain.access.log;
#error_page 404 /404.html;
location ~ html|css|js|jpg|png$ {
try_files $uri index.php
break;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/share/nginx/html;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /usr/local/etc/nginx/fastcgi.conf;
break;
}
}
Here we go we are done normally… but let’s check few stuff to make sure everything will start correctly
6. Check the config and restart
We check that all the plist are loaded:
$ launchctl list | grep php $ launchctl list | grep nginx $ launchctl list | grep mysql
You should see the plist file name if it’s loaded, if you don’t see anything it’s because you forgot to load it, read above and make sure you load the plist file.
Let’s restart and check it!
$ sudo reboot
Open a browser and check http://myfirstdomain.local:8080 and http://myseconddomain.local:8080
Everything should work, at least it’s working for me ![]()
If you have any trouble comment it please, I’ll try to help you and update the tuto.
Have fun!