Nginx server with PHP

Hi,

After successfully building nginx server, I wanted to share what I done. As, title suggest it is going to work with PHP, if request comes, I can write a django and codeigniter specific ones, but for now, I will keep it simple.

What you need?

  • nginx
  • FastCGI
  • php
  • php fastcgi module
  • Optional: An init script that I will provide

What to do

First, you need to install nginx, php5, php5 fcgi module. You can download them all from yast. They are in OSS or non-OSS I am not sure which one, but that wouldn’t be a problem.

After, downloading them all, you need to configure your nginx. Nginx configuration file resides in /etc/nginx/nginx.conf, you can check nginx.conf.default to get an idea, you can also look at my example config file (link below), as we are going to create it step by step later. Additionally, I’ll introduce how to create virtual hosts, although it is not done in my example config file.
My configuration: SUSE Paste

Configuration


pid /var/run/nginx.pid;
user  nginx nginx;
worker_processes  2;
events {
    worker_connections  1024;
}

In this part, we are defining nginx pid, user and group name. worker processes and worker connections. With this setup for example, you serve to 2*1024=2048 people. Next people will be rejected. I read from somewhere (that I cannot remember) that worker_processes recommended to be equal to number of your cores your processor has.

http{
.
.
.
}

In this part, we are defining a http server, all goes between is configuration of our server.


    include       mime.types;
    default_type  application/octet-stream;
    log_format main '$remote_addr $host $remote_user $time_local] "$request"'
                        '$status $body_bytes_sent "$http_referer" "$http_user_agent "gzip_ratio""';

        index  index.html index.htm index.php index.py;

We are including mime.types, to understand different file types, and defining default type we are serving. And also we are defining our index files, and log format. Although we didn’t defined any log files here, you can define by site, or for all http server.


server {
                server_name _;
                return 444;
        }

This is our first server definition. This server just server nothing. Servername of “_” indicates that this is for the cases where incoming connection doesn’t defined in config file. For example, localhost, or direct ip addres in this case.


server {
server_name <my server name was here>;
        root   <my root was here>;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
***
}

We are defining our first actual server here. server_name is quite easy to understand, it is your server name, for example, ::: YOURNAME.COM :::](http://www.yourname.com). root, as it is also clear, filepath to root of your website. We are also defining our error pages. With this setup, we will server 500 502 503 504 errors with /50x.html. Next we define a location, we can change root of website location base. So when nginx will serve equals /50x.html, it will look for it in /srv/www/htdocs/, your 50x.html is already installed there for you.

This configuration is enough to serve static pages. Before we go into details of php configuration, we need to spawn some php fastcgi’s. You can do it manually, from the command line, but I will explain how to do it as a daemon. Copy and paste this file (SUSE Paste) in /etc/init.d/php-cgi5. This is initscript for php-cgi5 and it will spawn 5 child processes for you, each taking 100 max request. With this setup, you can have 500 php request at one time. Modify it according to your needs. And then, go to yast-> runlevels and enable php-cgi5. If it goes OK you will have 5 processes waiting in port 900 for fastcgi requests. Let’s continue with setup.


location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
           include        fastcgi_params;
        }

We are defining a new location in this server. For locations ending with .php this code block will be executed. We are telling to look for fastcgi gateway at 127.0.0.1:9000, PHP should fcgi module should be waiting there is you used init script I provided. We are also defining SCRIPT_FILENAME to be used by fastcgi. And including fastcgi_params, this file should be present in your system if you installed nginx from yast.

Security Concerns

If you are allowing uploads to your server, passing every location ending with .php to php will cause a security holl. For example, someone could embed php in a image file and upload it to your server. Then can be execute that php code like this;
404 - Not Found

Nginx will send this to location to php, when php cannot file asdf.php it will look up, and find out that image_name.jpg exist and excutes it. This could damage your server SEVERELY. If you are allowing uploads, there are a few methods to fix this but these methods can differ according to your webpage setup (e.g. different CMS and Frameworks requires different configurations). So I will not get into details in this issue.

More Readings:

Configuration
https://calomel.org/nginx.html

I don’t know that it says this in the docs, but assuming your server is only running nginx, this will almost always give you optimal performance.
And if you’re using SSL or nginx is gzipping files, best practice is to set worker_processes equal to number of cores.

N.B. Your OS may still try to pin all worker processes to a single CPU. In that case you’ll need to override this using nginx’s worker_cpu_affinity.

Also, quoting seems to be broken using “Reply with Quote”

Thanks for the how to. I’ve used nginx some time in the past and IMHO is the easiest to use HTTP server yet.