Nginx with Different Versions of PHP FPM and PHP

nginxPHPphp-fpm

Due to a better understanding of what I wish to achieve thanks to Mark and his previous answer, I am posting a (hopefully) clearer and slightly different variation of my previous question as that thread has reached saturation;

I am trying to have multiple WordPress sites run on an nginx server, where each site requires a different version of PHP. I wish to achieve this by using multiple versions of PHP-FPM each running a different version of PHP, separate to nginx.

I then want to use .conf files to control which PHP-FPM server each site uses, allowing that site to run on the desired PHP version. (As per the comments section)

Currently my server block for testsite1 looks like this, running the default PHP version.

server {
    listen 80;
    listen [::]:80;

    root /usr/share/nginx/html/testsite1;
    index index.php index.html index.htm;

    server_name local.testsite1.com;

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}

This is located in /var/nginx/sites-available/testsite1 and is sym linked to /var/nginx/sites-enabled/testsite1. Each server block is location in a separate file within sites-available

testsite1
testsite2
testsite3

I have compiled a different version of PHP (5.3.3), but I am unsure how to set up multiple PHP-FPM servers and how to make each 'point' to a different version of PHP. I also need guidance on how to set up multiple .conf files to define which PHP-FPM server each WordPress site will use.

(essentially, I need hand holding throughout the entire process…)

Best Answer

In my experience, a simple server structure as follows, which is enough for your case.

Assumption

You have about two hours to set them up.

Server Environment Assumption

1 x Nginx server (Front-end, to process static files)

2 x PHP-FPM server (Back-end, to process PHP script)

1 x database server (Either in another separated server or in Nginx server is okay)

Nginx server can be accessed by Public Network and Private Network

PHP-FPM servers and DB server can only be accessed by Nginx server (Private Network)

Public Network, which means can be accessed by people who have internet.

Private Network, which can be seen in a specific network group. (Class A, Class B, Class C. Ex, 192.xx.xx.xx or 10.xx.xx.xx or 172.xxx.xxx.xxx)

If you are using VPS on Linode and DigitalOcean, both of them provide private network IP, you can follow the instruction given by them to set it up.

If not, you can set up your own VPN(Virtual Private Network) or use your router to build one, it's easy, you can GOOGLE all what you need.

If you are using Ubuntu, making a VPN with configuration only costs you less than 5 minutes.

Before next step, suggest you to set up the firewall rules to prevent potential attacks. (By using IPTABLES or its wrapper, FirewallD)

Although we make PHP-FPM as dedicated from Nginx, however, the PHP files of websites can't be passed through both TCP Port and Unix Socket.

Thus, you have to manage your root folder for web server.

Options to manage website folder

  1. Uploading your websites to Nginx server AND PHP-FPM servers with SAME folder PATH

  2. Write a script to synchronous files to all of your servers

  3. Using GIT to all your servers.

  4. Creating a NFS (Network File System) on Nginx or another dedicated server

If you are using *nix system, I suggest the forth option to do due to,

First, manage all your websites files in one server

Second, very easy to maintain

Third, backup in minutes (This should be another question)

※ NFS server acts as a pure storage server for your websites

Some people may consider using NFS cause network latency, however, as for multiple websites waiting to be managed, NFS is an efficient and simple way.

You can GOOGLE "NFS on Linux" to finish installing and configuring this step, costs you about 1 hour for newer.

However, be aware that NFS server should be in a Private Network as well.

When NFS, PHP-FPM and Nginx are both in the same Private Network, the network latency should be less.

Then let's config the nginx.conf

Assumption

Your Nginx public IP is 202.123.abc.abc, listen 80(or 443 if SSL enabled)

Your PHP-FPM 5.5 is on 192.168.5.5, listen 9008

Your PHP-FPM 5.6 is on 192.168.5.6, listen 9008

(additional example) Your HHVM 3.4 is on 192.168.5.7 , listen 9008

And you consider PHP 5.5 is your most used PHP version

    server {

         listen 80 default server;
         server_name frontend.yourhost.ltd;
         #root PATH is where you mount your NFS
         root /home/www;   
         index index.php;

    location ~ \.php$ {
        try_files  $uri $uri/ = 404;
        fastcgi_pass   192.168.5.5:9008;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PHP_VALUE  open_basedir=$document_root:/tmp/:/proc/;
        include fastcgi_params;
        fastcgi_buffer_size 512k;
        fastcgi_buffers 256 4k;
        fastcgi_busy_buffers_size 512k;
        fastcgi_temp_file_write_size 512k;
        fastcgi_intercept_errors on;

    }

    }
#Here to set up you vhosts
include vhosts/*.conf; 

Above lines should be put before the last }

Then, go creating a folder called vhosts inside the folder of nginx.conf

Assumption

You have another one application is using PHP 5.6

You have another application is using HHVM

For PHP 5.6 (vhosts/app1.conf)

       server {
         server_name app1.yourhost.ltd;
         listen 202.123.abc.abc:80;
         index index.php;
         #root PATH is where you mount your NFS
         root /home/app1;
         #Include your rewrite rules here if needed
         include rewrite/app1.conf;

         location ~ \.php($|/){
             try_files  $uri $uri/ = 404;

             fastcgi_pass   192.168.5.6:9008;
             fastcgi_index  index.php;
             include        fastcgi_params;
             set $path_info "";
             set $real_script_name $fastcgi_script_name;
               if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
                   set $real_script_name $1;
                   set $path_info $2;
                }
             fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
             fastcgi_param SCRIPT_NAME $real_script_name;
             fastcgi_param PATH_INFO $path_info;
            fastcgi_param  PHP_VALUE         open_basedir=$document$
         }
      location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
                    expires      30d;
      }

       location ~ .*\.(js|css)?$ {
                    expires      12h;
       }

        access_log  /var/wwwlog/app1/access.log access;
        error_log  /var/wwwlog/app1/error.log error;
     }

For HHVM (vhosts/app2.conf)

       server {
         server_name app2.yourhost.ltd;
         listen 202.123.abc.abc:80;
         index index.php;
         #root PATH is where you mount your NFS
         root /home/app2;
         #Include your rewrite rules here if needed
         include rewrite/app2.conf;

         location ~ \.hh($|/){
             try_files  $uri $uri/ = 404;

             fastcgi_pass   192.168.5.7:9008;
             fastcgi_index  index.hh;
             include        fastcgi_params;
             set $path_info "";
             set $real_script_name $fastcgi_script_name;
               if ($fastcgi_script_name ~ "^(.+?\.hh)(/.+)$") {
                   set $real_script_name $1;
                   set $path_info $2;
                }
             fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
             fastcgi_param SCRIPT_NAME $real_script_name;
             fastcgi_param PATH_INFO $path_info;
             fastcgi_param  PHP_VALUE         open_basedir=$document$
         }
      location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
                    expires      30d;
      }

       location ~ .*\.(js|css)?$ {
                    expires      12h;
       }

        access_log  /var/wwwlog/app2/access.log access;
        error_log  /var/wwwlog/app2/error.log error;
     }

In this way, you can even add different SSL certificates for your vhosts.

Restart your server, and enjoy!

EDITED

To install different versions of PHP-FPM, you can compile it yourself, or using existing stack.

Recommend https://github.com/centos-bz/EZHTTP/archive/master.zip to save your time

Using method, (Assumed your machine has installed WGET and UNZIP)

$ wget --no-check-certificate https://github.com/centos-z/EZHTTP/archive/master.zip?time=$(date +%s) -O server.zip

$ unzip server.zip

$ cd EZHTTP-master

$ chmod +x start.sh

$ ./start.sh

Choose 1 in the first screen

Choose 1 in the second screen (LNMP)

Choose 1 when asking you which version of nginx you want to install(do_not_install)

Choose 1 when asking you which version of mysql you want to install(do_not_install)

Choose what version you want when asking you which version of PHP you want to install

Remain all settings be the default (Make you manage PHP-FPM easily in the future)

Choose what extra extensions you want, of course you can ignore cause all common extensions will be installed later.

Let this shell start compiling!