Development

Serving PHP with Nginx on Ubuntu

For PHP developers, the ideal stack is Linux, Apache, MySQL and PHP (a LAMP server). However, being a Ruby developer, I tend to prefer Nginx over Apache, as well as Postgres over MySQL, but that’s another post.

Nginx is gaining against IIS and Apache because it’s very good at being a web server and uses fewer resources to do its job. And serving PHP with Nginx is easy to do, too. While most guides use custom FastCGI spawners and scripts, serving PHP with Nginx can be done even quicker and easier with mostly apt-get installed software.

Note: This was written for Ubuntu 12.04 and PHP 5.

Nginx from apt-get

First get the Nginx signing key so the server can trust the download and install the software provided by nginx.org.

wget http://nginx.org/keys/nginx_signing.key
apt-key add nginx_signing.key
rm nginx_signing.key

Add the nginx repo to /etc/apt/sources.list.d.

echo "deb http://nginx.org/packages/ubuntu precise nginx" > /etc/apt/sources.list.d/nginx.list

Note: I’m on Ubuntu 12.04 LTS, so I’m using “precise”. At the time of this writing, there is also “lucid”, “oneiric” and “quantal” builds available. Use the server’s version of Ubuntu in the command instead.

Then update the sources list and install Nginx.

apt-get update && apt-get install nginx

PHP

Instead of a custom spawner and init.d script, this setup will be based on PHP-FPM, which is “a simple and robust FastCGI Process Manager for PHP.”

apt-get install php5-cli php5-cgi psmisc spawn-fcgi php5-fpm

Edit the file /etc/php5/fpm/pool.d/www.conf so php-fpm will use a UNIX socket instead of a TCP/IP connection.

Look for listen = 127.0.0.1:9000 and change it to listen = /tmp/php5-fpm.sock.

PHP extensions

The application might require some additional PHP extensions to be fully functional. I tend to install the following extensions because they are required by a few big applications like Wordpress and ownCloud.

apt-get install php5-gd php-xml-parser php5-intl php5-curl

MySQL

Just for the sake of installing a complete stack (a LEMP server), MySQL is very easy to install. However, it might need some tweaking depending on the specs of the server and application needs.

apt-get install mysql-client mysql-server php5-mysql libmysqlclient-dev
mysql_secure_installation

Sample project

Before hooking everything up, I want show how I setup the default directory structure for most of PHP or static file projects to give some context to the Nginx config and the symbolic linking commands.

/home/deploy/apps
    |-- example.com          # project name
        |-- public           # web accessible directory
            |-- info.php     # file for testing install
        |-- config
            |-- nginx.conf   # server config file

The content of info.php:

<?php phpinfo(); ?>

The content of nginx.conf:

server {
  listen 80;
  server_name example.com;
  root /home/deploy/apps/example.com/public;

  index index.html index.php;
  client_max_body_size 1G;
  fastcgi_buffers 64 4K;

  location / {
    try_files $uri $uri/ index.php;
  }

  location ~ \.php$ {
    try_files $uri =404;

    include fastcgi_params;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/tmp/php5-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }
}

Serving the project

Nginx comes setup for multiple hosts out of the box. The configurations for available websites are in /etc/nginx/conf.d/. Start by deleting the default Nginx server.

rm /etc/nginx/conf.d/default.conf

Then link up the new project

ln -s /home/deploy/apps/example.com/config/nginx.conf /etc/nginx/conf.d/example.com.conf

Restart Nginx

service nginx restart

Wrapping up

The system parameters of the PHP install should be available at http://example.com/info.php. A caveat, though, is this is a quick way to serving PHP and some security precautions were taken, such as:

  • Running mysql_secure_connection
  • Separating publicly accessible files from other files in the project
  • Adding try_files $uri =404; to the Ninx server config

However, there is always more that can be done to secure a server.