How to setup a web server with Nginx/PHP on Raspberry Pi

Installing and Configuring Nginx

Running a web server is one of the most common uses for the Raspberry Pi. In this tutorial I’m going to show you how to setup Nginx for serving static files (HTML, PNGs, etc.) but I’m also going to show how you how to set it up so that we can also serve PHP (which is probably the most popular server-side scripting language used on Linux). Let’s get started.

The first thing we’re going to do is update our software sources and install Nginx.

sudo apt-get update
sudo apt-get install nginx

At this point the service isn’t running yet so you can start it with this command.

sudo service nginx start

With the service running, go ahead and navigate to your Pi’s IP in a web browser and you should see the following page. This is the default page for Nginx, so if we see this then we know it’s working.

Nginx default page

By default Nginx serves its static content out of /usr/share/nginx/www. However, the convention among the Linux community is to serve these files out of /var/www since this is commonly how Apache is configured. This folder doesn’t exist by default so we’re going to create it.

sudo mkdir /var/www

Before we proceed I should explain how Nginx virtual host configurations are organized. Nginx configuration files allow for a person to specify multiple sites that can be hosted by a single server. The convention is that each of these virtual host configurations is stored in its own file. Within /etc/nginx you’ll see a sites-available folder, this is where these the virtual host files are stored. When Nginx actually starts up it looks at another folder, sites-enabled, to see if there are any configuration files enabled. To enable a new virtual host configuration you just make a symlink in the sites-enabled that points to the configuration file in the sites-available folder. And likewise if you wanted to stop serving a site you just remove the symlink for it in the sites-enabled folder.

So the process I just described is exactly what we’re going to go through right now. If you look in the sites-enabled folder you’ll just see a file called default. This is Nginx’s default virtual host file that serves out /usr/share/nginx/www. I always like to start fresh, so we’re going to go ahead and disable that one.

sudo service nginx stop
sudo unlink /etc/nginx/sites-enabled/default

Now let’s go ahead and create a new virtual host config at /etc/nginx/sites-available/mysite. And put the following in it.

server {
        listen 80;
        root /var/www;
        index index.html index.htm;

This is probably the most basic config file you can have. We’re telling Nginx to listen on port 80 (default for HTTP traffic), use/var/www as the root folder for serving out our files, and then we tell it the filenames that’ll be used when looking for the index page. With that saved, let’s enable it and turn Nginx back on.

cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/mysite
sudo service nginx start

And if you place a simple HTML file in /var/www now you should be able to navigate to it in your browser. If you’re curious about the more detailed configuration options then have a look at the Nginx wiki.

Installing and Configuring PHP

With Nginx all setup, we can now go ahead and install PHP. Now the way PHP and other server side languages work is that they run in a process apart from Nginx. Nginx merely handles the web requests and will send the request over to PHP if PHP code needs to executed. Once PHP is done it returns the response back to Nginx. There are several different technologies for handling this communication between PHP and the web server. Aside from Apache, most web servers use one called FastCGI. So we’re actually going to be installing PHP-FPM which is a FastCGI interface that will allow Nginx to send requests to PHP. Along with that we’re also going to install a PHP extension called APC that greatly helps accelerate PHP’s performance. Let’s install it with the following command.

sudo apt-get install php5-fpm php-apc

After that the service should automatically be started and running. But we’ll want to restart it to make sure that the APC extension got loaded.

sudo service php5-fpm restart

Now we just need to modify our virtual host configuration file slightly so that it knows where to send the PHP requests. Open up/etc/nginx/sites-available/mysite in a text editor and modify it so that it looks like the following.

server {
        listen 80;
        root /var/www;
        index index.php index.html index.htm;

        location ~ \.php$ {
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi_params;

What we’ve done here is tell Nginx that any requests ending in php need to be passed to PHP-FPM. We’ve also specified that we want to add index.php as an index page in addition to index.html and index.htm. Now with those changes we should be good to go so let’s create a test file at /var/www/test.php and put the following PHP code in it.

And lastly let’s restart Nginx for the virtual host changes to take effect.

sudo service nginx restart

Load up a browser now and point it to http://<your Pi’s IP>/test.php and you should get the following output.

PHP information page

And there you have it, your Raspberry Pi is now setup as a lightweight web server that can serve static files and PHP.

  • Michel Matton

    what about mysql? any issues running mysql on an nginx web server?

    • Ben Hanna

      You shouldn’t have any problem with an existing MySQL installation. The setup of MySQL is completely independent of the Nginx (or Apache) and PHP install, so you don’t need to modify anything to make it work with this setup.

  • Eric Murray

    Great guide, however, you need to alter this line in mysite config:
    fastcgi_pass pass:/var/run/php5-fpm.sock;

    Change to:
    fastcgi_pass unix:/var/run/php5-fpm.sock;

    That’s all.

    • Ben Hanna

      Typo on my part it’s fixed now, thanks for catching that.

  • southafricanrob

    hi – i am running an image called pimusicbox based on raspbian that already has a web interface served from /opt/weblient but doesn’t have support for php. I’ve tried editing the config above to use /opt/weblient as root but no luck, am I on the right path?

  • AdamTheRPiNoob

    Great guide! Very easy to follow, and unlike many other guides out there, you take the time to explain why things are installed and tweaked; rather than just saying run this command, then edit this config file and there you go… it works!

  • grip

    Very nice, thanks! this is exactly what I was looking for, apache seems a bit too heavy for the PI

  • aminpro

    Thank you! Works perfectly!

  • scHoolboy Q

    tHank you so mucH, tHis was just wHat i needed to make it easier for me to develop, HaHa

  • Mo Yang

    thank u so much, it is useful to me!

  • atrioom

    Hey man, thanks for the effort of explaining the components in detail. Normal tutorial just tell you to do a) and b) but you go into detail and that’s SUCH A RELIEF! I actually learned something. Have a nice day.

  • Spy Gi

    Worked like a charm! Thanks for taking the time to explain stuff as well :)

  • cauboy

    Good Tut. Very understandable.

  • Mariusz Kujawski

    Wow! That was quick! Thank you for this guide. :)

  • Jan

    thanks for this great tutorial. But if I following your instructions i get these error:
    Starting nginx: nginx: [crit] pread() “/etc/nginx/sites-enabled/mysite” failed (21: Is a directory)
    nginx: configuration file /etc/nginx/nginx.conf test failed

    I think you should rewrite the part with the config file for nginx.

    • Ben Hanna

      Based on that error it sounds like you created /etc/nginx/sites-enabled/mysite as a directory or linked it to a directory.

  • afrab

    Should you include instructions to establish a link from phpmyadmin’s source folder to nginx’s reassigned html root folder; specifically, “sudo ln -s /usr/share/phpmyadmin/ /var/www” (or whatever folder is set up as nginx’s html source)? Otherwise, when you try to open phpmyadmin from a browser (e.g., “http://localhost/phpmyadmin”), you’re gonna get a “Page not found” response, instead of phpmyadmin’s login scren.

  • udon

    how about “nginx-light”? It seems that nginx-light cannot handle embedded PHP, even though just PHP statement works fine. What I tried was testPHP . Is there any way to make it work on nginx-light?

  • YarharALC

    Nice job as always!