Services Spotlight:

How To Install PHP5 (using php-fpm) for Nginx on Ubuntu 14.04

Written By Corlew Solutions
Updated November 11, 2014
Published May 5, 2014
Why Corlew Solutions?

We write great software and provide amazing technical support. Contact us today if you need help with a software project:

Article Technology Info

This article discusses the following technologies:

  • Nginx - An free HTTP and mail server
    (website | download | docs | wiki)
  • PHP - A popular general-purpose scripting language that is especially suited to web development.
    (website | download | docs)
  • php-fpm - An alternative PHP FastCGI implementation that is useful for busier sites.

Getting PHP working on Ubuntu with Nginx is fairly challenging, even for someone who knows what they are doing. There are many cryptic terms and endless configuration options. This article will walk you through the process of installing PHP using the PHP5-fpm package. It assumes you already have a working installation of Nginx and would like to add PHP capabilities to your web server. We intend to use this article as a reference document for our own installations and we will be updating it as we solve problems and learn new tricks.

Let’s get started!

Install PHP

A quick search through the available packages on Ubuntu using sudo apt-cache search php5 shows there are two primary packages available for installing PHP5 with Nginx: php5-cgi and php5-fpm. These packages are maintained by the Ubuntu developers and either can be used to add PHP.

Install PHP5 using the php5-fpm package:

php-fpm started as a separate project from PHP, but it was incorporated into PHP as of PHP 5.4. It’s the new kid on the block and many people are switching to it since it’s a bit faster, especially under higher server loads.

1
sudo apt-get install php5-fpm

That’s all there is to it. When the installation finishes, you should see a message in the output about the service being starting. Let’s verify that this is accurate.

Verify PHP5 Is Running

Here are two ways to verify the status of the PHP5 service:

Method 1

We can use the ps command to get a list of processes and then pass that list to the grep command to filter on the term php5:

1
ps -waux | grep php5

If php5-fpm is running you should get output similar to:

1
root      2651  0.0  0.6 221456 13792 ?        Ss   00:23   0:02 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)

Method 2

We can take advantage of the service or status command:

1
2
status php5-fpm
service php5-fpm status  

If the service is running you should see a message like:

1
php5-fpm start/running, process 2651

If the service is not running you should see a message like:

1
php5-fpm stop/waiting

Method 3

When php5-fpm is running, you should find a php5-fpm.sock file in your /var/run directory. (Note: On some systems, the file may be located in /tmp.) You can verify this by running:

1
2
ls /var/run/php5-fpm.sock
ls /tmp/php5-fpm.sock

Start and Stop php5-fpm

Many tutorials on the internet claim php5-fpm can be started and stopped using sudo /etc/init.d/php5-fpm stop or sudo /etc/init.d/php5-fpm start. This is the old way of working with php5-fpm and depending on your system it may no longer work. The new way is to use the service command:

1
2
3
4
sudo service php5-fpm stop
sudo service php5-fpm start
sudo service php5-fpm restart
sudo service php5-fpm status

Ubuntu is in the process of changing to the service method and you will likely run into this issue in the future. You can read more about Ubuntu’s rational for moving here.

Install Optional Packages and Modules

There are many other PHP5 related packages that add capability to PHP5. If you plan on running a Wordpress site you will definitely need some of these extra modules. You can browse through the list of modules by executing the following command:

1
sudo apt-cache search php5

Alternatively, you can browse packages from Ubuntu’s website. Here’s a shortcut that lists all of the PHP5 related packages for Ubuntu 14.04.

1
2
3
4
5
6
sudo apt-get install php5-gd  # Popular image manipulation library; used extensively by Wordpress and it's plugins.
sudo apt-get install php5-cli   # Makes the php5 command available to the terminal for php5 scripting
sudo apt-get install php5-curl    # Allows curl (file downloading tool) to be called from PHP5
sudo apt-get install php5-mcrypt   # Provides encryption algorithms to PHP scripts
sudo apt-get install php5-mysql   # Allows PHP5 scripts to talk to a MySQL Database
sudo apt-get install php5-readline  # Allows PHP5 scripts to use the readline function

There are many other modules available. If you want more details on any particular package, the following command may come in handy:

1
sudo apt-cache show (package name)

If you installed any new packages, make sure to restart the php5-fpm service.

1
sudo service php5-fpm restart

Install php5-mysql (Optional)

By default PHP can’t talk to a MySQL database. If you plan on connecting to MySQL, you will have to enabled this capability by installing another module. This section assumes you already have MySQL installed on your system. If you need instructions on how to install MySQL server, checkout our article about how to install MySQL on an Ubuntu server.

Connecting PHP to MySQL is very easy. Simply install the associated module:

1
sudo apt-get install php5-mysql

Add Nginx Server Definition

Determine Connection Method and Configure php-fpm

At this point you need to decide if you want php-fpm and Nginx to communicate via unix sockets or TCP IP. In theory, Unix sockets should be faster because there’s much less overhead involved, but the answer isn’t clear. Whichever way you choose, we need to make sure php-fpm and Nginx are on the same page. We’ll explain how to do it both ways.

First let’s edit the necessary configuration file for php-fpm:

1
sudo nano /etc/php5/fpm/pool.d/www.conf

Scroll down until you find the line that starts with listen =. If the value says 127.0.0.1:9000 then php-fpm thinks it is communicating over ip on port 9000. If it says /var/run/php5-fpm.sock then fpm is trying to communicate via the socket. You may choose either strategy here that you like. Whichever you choose, make sure to remember the value because we will need to give it Nginx later. Make your edits (if necessary), save and close the file.

Somewhere around PHP 5.5.12, the PHP team decided to fix a permission bug. This change requires us to make some additional edits to the www.conf file. Find the lines that look like

1
2
3
listen.owner = www-data
listen.group = www-data
listen.mode = 0660  # Your file might have a ";" in in front which indicates the line is commented out.  0660 is the default.

Prior to the change in PHP, we didn’t really need to change these lines. You can read more about the issue here, but in short, it will cause a 502 Bad Gateway error to generated when users visit the site. If, you take a look at the right server log file you’ll see “permission denied” errors by Nginx when it tries to access the socket.

As a result of the change we now need to make sure Nginx and PHP are using the same user/group. It is common for web servers to use www-data as the default user/group, but many people like to change this user/group to something like nginx/nginx. Whatever you’re using, make sure Nginx and PHP are using the same user/group. Change the listen.owner and listen.group lines accordingly.

If you scroll up a bit in the www.conf file, you’ll see two more lines:

1
2
user = www-data
group = www-data

Change those lines to match the correct user/group as well. That’s it for the www-conf file. We will handle defining our website for Nginx next.

Configure nginx.conf

We need to tell Nginx our website exists. We could add site definitions directly into the nginx.conf file, but we find that it easier to manage if each site is defined in it’s own file. To do this, we need to first tell Nginx where to find these files.

Open up your nginx.conf file.

1
sudo nano /opt/nginx/conf/nginx.conf

Add the following line inside your http section:

1
include /etc/nginx/sites-enabled/*;

This tells nginx to look in the specified directory and merge all of the files that are found into the nginx.conf file when the server starts.

Define the Site

Next, let’s create that sites-enabled directory from above and another directory called sites-available. The sites-available directory will hold our real site definition files and the sites-enabled directory will hold symlinks pointing to those files. By structuring things this way, we can easily deactivate a site by removing the symlink while still keeping the site definition (in case it is needed later). You can place these directories anywhere you like, but one convention is to put them in the /etc/nginx directory. If you installed Nginx via the package manager then these directories likely already exist. If they do not exist, create them now:

1
2
sudo mkdir -p /etc/nginx/sites-available
sudo mkdir -p /etc/nginx/sites-enabled

Next, create a new file in sites-available to hold the site definition. The file can be named anything you like; the domain of the website is a sensible choice:

1
sudo nano /etc/nginx/sites-available/example.com

Copy the following server definition into the file and change references to /srv/www/example.com to something appropriate for your site.

 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Listen for requests to the www version of the site and redirect all
# requests to the non www version.  Flip this around if the other
# way is desired
server {
  listen 80;
  server_name www.example.com;
  rewrite ^ http://example.com$request_uri?;
}

# Listen for requests to the non-www version of the website.
server {
   listen 80;
   server_name example.com;
   access_log /srv/www/example.com/log/access.log;
   error_log /srv/www/example.com/log/error.log;
   root /srv/www/example.com/public_html;
   charset UTF-8;

   # If only the root URI is given, try these files in order until one is found
   index index.php index.html index.htm;

   # Don't fill up the log file with messages about a missing favicon
   location = /favicon.ico {
        log_not_found off;
        access_log off;
   }


   # If a .git directory happens to be uploaded to the server, don't allow access
   location ~ /\.git/* {
        deny all;
   }

   # Adds ability to view some status info about nginx
   location /nginx_status {
        stub_status on;
        access_log off;
   }

   # Try to serve the file at the exact URI, a URI with a /.
   # The last term /index.php?q=$uri&$args is a nod to Wordpress which
   # drives many of it's pages off /index.php.  It may not be needed depending
   # on the website.
   location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
   }

   # Pass php files off to php-fpm
   location ~ \.php$ {
       # If php-fpm is communicating with nginx via TCP IP, then uncomment/comment next two lines
       # fastcgi_pass 127.0.0.1:9000;
       fastcgi_pass unix:/var/run/php5-fpm.sock;
       fastcgi_split_path_info ^(.+\.php)(/.*)$;
       fastcgi_index index.php;
       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
       include fastcgi_params;
   }

   # Settings for asset files
   location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
   }

   # deny access to apache .htaccess files
   location ~ /\.ht {
       deny all;
   }

}

Next, we need to create the symlink in sites-enabled and point it to the site definition we want to enable in sites-available. Be sure to change example.com in the command below to your actual file name:

1
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled

Learning how to configure an Nginx site definition is a complex topic; the above definition should get you up and running for a PHP based website, but much more is possible. If you’re interested in digging deeper, pickup a copy of Nginx HTTP Server Second Edition.

Prepare Website Directories

We need a place to store the website files so let’s prepare some directories. If you take another look at the site definition file we just created, we told Nginx to expect some files and directories to be in place. Let’s set that up now.

1
2
3
4
5
sudo mkdir -p /srv/www/example.com
sudo mkdir /srv/www/public_html
sudo mkdir /srv/www/example.com/log
touch /srv/www/example.com/log/access.log
touch /srv/www/example.com/log/error.log

Change Ownership

Make sure the current user owns the new website directory. Make sure to change user:user

1
sudo chown -R user:user /srv/www/example.com

Test Installation

Restart Nginx.

1
/etc/init.d/nginx restart

Test PHP is working by creating a test.php file in the root directory you specified above. The file should just include:

1
<?php phpinfo(); ?>

If everything has gone well, you should see the PHP info page.

We hope you found this article useful. If you see any mistakes, missing features or ways to improve it, please let us know in the comments below so we can update its contents. If you're willing to link to us, we would sincerely appreciate it!

Corlew Solutions is a Web Design and Web Application Development company based in Fairfax Virginia, minutes away Washington D.C. If you're looking for great web design from the Northern Virginia area or web design from the Washington D.C. area we can help. Contact Us today!

comments powered by Disqus