How to install Nginx and PHP-FPM on CentOS

Nginx is a very popular web server in recent years. It is very well known for being used as a high performance web server, a reverse proxy server, or even a load balancer. Some differences Nginx has from Apache:

- No built in PHP support (mod_php).
- Apache is process based while Nginx is event based.
- Modules in Nginx are compiled directly into the binary while Apache has installable modules that can be enabled or disabled quickly
- Nginx configuration files are a series of includes for each sites configuration, whereas Apache has global settings and a companion virtual host with overrides for customization.  So this means there is no override file like Apache's .htaccess in Nginx.
- There are no SSLCertificateChainFile in Nginx.  Intermediate CA certificates need to be appended directly to the site's SSL certificate.

At this time, the current best practice for installing Nginx is to use Nginx’s repos directly as they will contain the most recent and stable releases of Nginx. So install the repo package for Nginx by:

# CentOS 6
[root@web01 ~]# rpm -i http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
[root@web01 ~]# rpm --import http://nginx.org/keys/nginx_signing.key
[root@web01 ~]# yum install nginx

# CentOS 7
[root@web01 ~]# rpm -i http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
[root@web01 ~]# rpm --import http://nginx.org/keys/nginx_signing.key
[root@web01 ~]# yum install nginx

As Nginx does not have anything to natively process PHP, install php5-fpm by:

[root@web01 ~]# yum install php-fpm

By default, php-fpm will be listening for connections over TCP. This is incredibly slow when Nginx and php-fpm are on the same server. So modify the php-fpm configuration from listening over TCP to using sockets by:

[root@web01 ~]# vim /etc/php-fpm.d/www.conf
...
[www]
listen = /var/run/php5-fpm.sock
...

Now set php-fpm to run as user nginx:

[root@web01 ~]# vim /etc/php-fpm.d/www.conf
...
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx
...

Set php-fpm to start on boot, and then startup the service:

# CentOS 6
[root@web01 ~]# chkconfig php-fpm on
[root@web01 ~]# service php-fpm start

# CentOS 7
[root@web01 ~]# systemctl enable php-fpm.service
[root@web01 ~]# systemctl start php-fpm.service

Back in Nginx, configure it to send any PHP requests to the php-fpm socket inside of the http{} block:

[root@web01 ~]# vim /etc/nginx/nginx.conf
http {
...
upstream php5-fpm-sock {
     server unix:/var/run/php5-fpm.sock;
}
...
}

Now that Nginx and php-fpm are configured, setup your first site:

[root@web01 ~]# mkdir -p /var/www/vhosts/example.com
[root@web01 ~]# vim /etc/nginx/conf.d/example.com.conf
server {
     listen 80;
     server_name example.com www.example.com;

     root /var/www/vhosts/example.com;
     index index.php index.html index.htm;

     access_log /var/log/nginx/example.com-access.log;
     error_log /var/log/nginx/example.com-error.log;

     location ~ \.php$ {
          expires off;
          try_files $uri =404;
          include /etc/nginx/fastcgi_params;
          fastcgi_pass php5-fpm-sock;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     }

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

#server {
#      listen 443 ssl;
#      server_name example.com www.example.com;
#
#      root /var/www/vhosts/example.com;
#      index index.php index.html index.htm;
#
#      access_log /var/log/nginx/example.com-ssl-access.log;
#      error_log /var/log/nginx/example.com-ssl-error.log;
#
#      ssl_certificate /etc/pki/tls/certs/YYYY_example.com.crt;
#      ssl_certificate_key /etc/pki/tls/private/YYYY_example.com.key;
#
#      ssl_session_timeout 5m;
#
#      # Use PCI compliant SSL protocols and ciphers
#      ssl_protocols SSLv3 TLSv1;
#      ssl_ciphers HIGH:!kEDH:!ADH:!EXPORT56;
#      ssl_prefer_server_ciphers on;
#
#      location ~ \.php$ {
#           expires off;
#           try_files $uri =404;
#           include /etc/nginx/fastcgi_params;
#           fastcgi_pass php5-fpm-sock;
#           fastcgi_index index.php;
#           fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#      }
#
#      # caching of files
#      location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
#           expires max;
#           log_not_found off;
#      }
# }

Finally, start Nginx and enable it to start on boot:

# CentOS 6
[root@web01 ~]# chkconfig nginx on
[root@web01 ~]# service nginx start

# CentOS 7
[root@web01 ~]# systemctl enable nginx.service
[root@web01 ~]# systemctl start nginx.service

NOTE : There is no SSLCertificateChainFile in nginx. CA Certs need to be appended to the certificate for the domain.

Troubleshooting

If you see a page that says ‘The page you are looking for is currently unavailable’, you’ll find Nginx is having trouble getting data from php-fpm (while using a socket). Make sure that the socket you specify in the nginx.conf and the listen line in www.conf pool file for PHP-FPM match.

If you get a ‘File Not Found’ page only on php pages (when using a TCP port for php-fpm) you can check the nginx logs, and you’ll probably see an error indicating it couldn’t connect on the port. Its possible this could be happening if you need to move the root and index definitions out of a location block (if they are defined there). This is because the php section has it’s own location, the documents won’t try to be found using definitions in the domain ‘location /’ block.