I still got sites running Apache, but all new projects are launched with Nginx. I don't need many of the features that Apache offers, and the speed gain of Nginx is just tremendous. Once you've experienced it, I doubt you'll want to go back.
Update - May 2nd, 2013
The official CakePHP documentation now includes a good Nginx section. This article is hence deprecated and should only be looked at for Cake 1.3 installations.
Update - Feb 24th, 2013
Chris Hartjes takes a similar approach in articles written way before mine, be sure to check it out!
Continuing
Even though there has been quite some fuzz about Nginx and I bet most of you have at least heard of it by now, I think the acceptance is still a bit low.
I'd like to help that process along by providing developers a simple yet effective example.
Maybe you'll play with it on your local box - and eventually decide to go production. Who knows.
Let me show you how easy it is to get hooked to the power of Nginx.
In this article I'm demonstrating a CakePHP setup, but 1 slight modification and this applies to pretty much any PHP Framework.
So there are a few differences from your typical Apache setup that I'd like to highlight.
Install Nginx
If you're running Ubuntu like me it helps to have Karmic or higher. Then just type:
$ aptitude install nginx
Other operating systems: it shouldn't be much harder then that, just replace aptitude with your package manager.
If you find yourself compiling you're on the wrong track, and going to spe nd way too much time on this.
Don't forget to shut down any existing web servers you may have.
PHP FastCGI: spawn-fcgi
In this setup, PHP is daemonized and keeps running as a process, listening to a socket.
Nginx will be configured to pass any *.php requests to this PHP process. Normally PHP would have to be fired up all the time. But now it resides in memory.
To install spawn-fcgi in Ubuntu you'd do:
$ aptitude install spawn-fcgi php5-cgi
# It doesn't provide a startup script yet. Here's how to get one:
$ curl https://raw.github.com/kvz/deprecated/kvzlib/configs/spawnfcgi_initd -ko /etc/init.d/spawn-fcgi \
&& chmod a+x $_
$ update-rc.d spawn-fcgi defaults
Now start it with:
$ /etc/init.d/spawn-fcgi start
Excellent. PHP is listening on port 9000 for incoming Nginx jobs.
You can configure your new PHP install like you're used to.
Only in this directory: /etc/php5/cgi/
instead of this one /etc/php5/apache2/
Alternative: php-fpm
There also is php-fpm. Pretty much does the same thing, but faster.
Unfortunately at the time of writing I'm experiencing too many crashes for it to be recommendable. This will probably change soon though.
HtAccess
It's true that Nginx doesn't support .htaccess, but to be honest: .htaccess files are the worst.
The additional recursive dir-stats, I/O, & processing involved with every request, is equal to the exact amount of punches in the face.
That it doesn't support .htaccess does not imply however, that you can't do rewrites and all the other fancy things you could do with .htaccess files.
Just slightly modify the syntax, and place those new rules in your Nginx VHost.
As a present, I've already converted the .htaccess rules required to run CakePHP, and put them in the Nginx VHost example below.
Nginx Vhost
VHost concept works the same as Apache. Have 1 for every site.
Save it in /etc/nginx/sites-available/site
. To activate, symlink it to /etc/nginx/sites-enabled/site
run:
$ /etc/init.d/nginx reload
..and you're in business. Use
$ tail -f /var/log/nginx/*.log
to see what's going on.
You don't need to change Nginx's main config, it's tight by default so just stick with your VHost for now.
Here's what a fully working CakePHP VHost looks like:
server {
listen 80;
server_name example.com www.example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
rewrite_log on;
root /var/www/example.com/app/webroot;
index index.php index.html index.htm;
# Not found this on disk?
# Feed to CakePHP for further processing!
if (!-e $request_filename) {
rewrite ^/(.+)$ /index.php?url=$1 last;
break;
}
# Pass the PHP scripts to FastCGI server
# listening on 127.0.0.1:9000
location ~ \.php$ {
# fastcgi_pass unix:/tmp/php-fastcgi.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on; # to support 404s for PHP files not found
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Static files.
# Set expire headers, Turn off access log
location ~* \favicon.ico$ {
access_log off;
expires 1d;
add_header Cache-Control public;
}
location ~ ^/(img|cjs|ccss)/ {
access_log off;
expires 7d;
add_header Cache-Control public;
}
# Deny access to .htaccess files,
# git & svn repositories, etc
location ~ /(\.ht|\.git|\.svn) {
deny all;
}
}
Notes about the example
- Nginx config is simple & powerful. If you want you can use if statements and put some very basic logic in there.
- In this example the /app/webroot is the document root. Some people may have a / as their CakePHP webroot or even /app. But I recommend changing that to /app/webroot so you're not exposing any more PHP files then is strictly required.
- Notice how this config turns off access log for some static files? How cool is that?!
- Checkout how simple it is to set expire headers for different content types
- Change example.com to your domainname
Free Bonus
Here's a VHost if you'd want to use phpmyadmin as installed in by Ubuntu's Apt:
server {
listen 80;
server_name phpmyadmin.example.com;
root /usr/share/phpmyadmin;
index index.php;
# Add your IP to the allow list!
location / {
allow 123.123.123.123;
deny all;
}
location ~ \.php$ {
index index.php index.html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on; # to support 404s for PHP files not found
include fastcgi_params;
}
}
I'm keeping the larger code blocks on GitHub so it'll be really easy for you to download, fork etc.
For instance I have another CakePHP configuration that's a bit bigger - shows you some other stuff you can do with Nginx here
That's it
Now go out there, have fun, tell me your findings.