Nginx by examples: PHP setup

When setting up PHP with Nginx we are effectively still using Nginx as a reverse proxy in front of a FastCGI server as the fastcgi_pass directive is functionally equivalent to the proxy_pass one.

There are plenty of blog posts and examples online that show how to setup PHP behind nginx but most of them don’t really explain why the suggested setup simply works :)

Let’s start with a simple configuration:

server {

  root /var/www/;
  index index.php;


  access_log /var/www/;
  error_log /var/www/ error;

  location / {

    # we serve a file if it's there, 
    # otherwise we rewrite internally as a request to /index.php
    try_files $uri /index.php?$args;

  # regex matching: anything ending with .php
  location ~ \.php$ {

    # allows for requests to /test.php/article/0001 
    # to be handled by /test.php. At the same time 
    # it sets the $fastcgi_path_info env variable 
    # (that can be sent to php via the fastcgi interface)
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    # defaults calls to /uri/ to /uri/index.php (optional)
    fastcgi_index index.php;

    # sets the standard fastcgi parameters (from another file)
    include fastcgi_params;

    # if the rewritten $uri doesn't really exist 
    # let's return 404 to the user
    try_files $uri =404;

    # let's pass the request to the fastcgi downstream


Request resolution process #

The main point here is to understand how the

location / {
    try_files $uri /index.php?$args;

and the

location ~ \.php$ {

interact with each other

In the catch-all location / {} block the tryfiles directive matches any incoming request not ending with .php
If the request has:

Apache Mod Rewrite #


Now read this

Premature optimization

Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are... Continue →