halkyon.net

Setting up nginx, PHP-FPM, and SilverStripe on Fedora 19

This guide will get you started with nginx and PHP-FPM to serve PHP scripts and use CMS and frameworks like SilverStripe on your Linux server. You could also expand on this to include configuration for Wordpress, Drupal, or others as you see fit. I wrote this guide using Fedora 19 on DigitalOcean cloud hosting, but some of it can be translated across to other flavours of Linux too.

nginx and PHP-FPM is a light and memory efficient alternative to Apache and mod_php. Because PHP requests are handled as a separate PHP-FPM connection pool, this doesn't affect the web server's ability to serve static files while PHP requests are running simultaneously. PHP running as FastCGI in general has a smaller memory footprint, and with FPM has more configuration options.

Installing base software

yum update
yum install nginx php-fpm php-opcache php-tidy \
php-xml php-pdo php-mcrypt php-mbstring php-gd
yum clean all

On Fedora 19, this will install nginx 1.4 and PHP 5.5 including Zend OPcache, a replacement for APC on PHP 5.5. At the time of writing, these are bleeding edge versions.

Configuring PHP

Edit /etc/php.ini and change cgi.fix_pathinfo to 0. This is for security reasons when running PHP as FastCGI to avoid requests like /something.jpg/index.php which could execute an uploaded PHP script hidden as an image.

The php-fpm package with Fedora defaults to running as the apache user. We're using nginx entirely without Apache, so let's get rid of that and run it under nginx instead:

userdel apache
chown -R nginx:nginx /var/log/php-fpm
mkdir /var/lib/php/session
chown -R nginx:nginx /var/lib/php/session

Edit /etc/php-fpm.d/www.conf and look for existing values for the following and fix them up:

listen = /var/run/php5-fpm.sock
user = nginx
group = nginx

You may also want to tweak the pm.max_children and pm.max_spare_servers values to accomodate your server's amount of RAM. For example, having 1 GB RAM would yield you a pm.max_children value of around 16 to 20, assuming around 40 MB per process and around 200-400 MB overhead for the operating system.

Configuring nginx

In Fedora and Red Hat like Linux, fastcgi_params is missing SCRIPT_FILENAME which we need. Edit /etc/nginx/fastcgi_params and add it in as follows:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

We'll now add some common configuration files for PHP and SilverStripe.

Create /etc/nginx/php.conf with the following:

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

Create /etc/nginx/silverstripe.conf with the following. Mostly taken from SilverStripe nginx installation docs:

location / {
try_files $uri @ss;
}
location @ss {
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param SCRIPT_FILENAME $document_root/framework/main.php;
fastcgi_param SCRIPT_NAME /framework/main.php;
fastcgi_param QUERY_STRING url=$uri&$args;
fastcgi_buffer_size 32k;
fastcgi_busy_buffers_size 64k;
fastcgi_buffers 4 32k;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
}
# block access to anything beginning with a dot (e.g. .htaccess, .htpasswd)
location ~ /\. {
deny all;
}

# deny access to silverstripe-cache
location ~ ^/silverstripe-cache {
deny all;
}
# don't execute scripts in the assets path
location ^~ /assets/ {
try_files $uri $uri/ =404;
}
# block access to yaml files
location ~ \.yml$ {
deny all;
}
# cms & framework .htaccess rules
location ~ ^/(cms|framework|mysite)/.*\.(php|php[345]|phtml|inc)$ {
deny all;
}
location ~ ^/(cms|framework)/silverstripe_version$ {
deny all;
}
location ~ ^/framework/.*(main|static-main|rpc|tiny_mce_gzip)\.php$ {
allow all;
}

Creating a new nginx "virtual host"

nginx uses server definitions for each site which tell nginx where it's files are, and which domains should be listened on. Those familiar with Apache will know them as virtual hosts, but they're similar.

For example, if you want to setup a new site called mysite.com, a domain that points to your server, and it's files are located in /var/www/html/mysite.com then add something like this to /etc/nginx/conf.d/mysite.com.conf:

server {
listen 80;
root /var/www/html/mysite.com;
server_name mysite.com;

error_log /var/log/nginx/mysite.com.error.log;
access_log /var/log/nginx/mysite.com.access.log;
include /etc/nginx/php.conf;
include /etc/nginx/silverstripe.conf;
}

The include lines effectively copy in configuration from php.conf and silverstripe.conf into this server definition so it knows how to handle a PHP or SilverStripe request.

Note: Files within /etc/nginx/conf.d are loaded automatically.

Opening up nginx write access in SELinux

Fedora enables SELinux by default, which blocks nginx and PHP-FPM from writing to any files.

Assuming your webroot is at /var/www/html, this rule will let nginx write to any files within that path:

chcon -R -h -t httpd_sys_script_rw_t /var/www/html

If you only want it to write to specific paths, such as the "assets" folder in your specific SilverStripe site path, you can tighten up the above command to a more specific path.

Note that SilverStripe will need write access to a few files during installation, so you might need to allow full access initially, then tighten it up after installation.

Enable nginx and PHP-FPM services

Fedora doesn't start nginx or PHP-FPM on boot. These commands will ensure it's enabled and started:

systemctl enable nginx.service
systemctl start nginx.service
systemctl enable php-fpm.service
systemctl start php-fpm.service

Finishing

Now you should have nginx and PHP setup, ready to go.

Next steps would be to install a database like MySQL or PostgreSQL if you need something other than SQLite, as well as tweak nginx settings like gzip in /etc/nginx/nginx.conf.
Head on over to the nginx wiki for more information and examples.