Install Nginx, PHP and MySQL

I’m going to use nginx rather than the more traditional Apache2, because it is more efficient and on a low-power device like the Pi that’s going to be important. I’m also going to install PHP5 (with PHP APC to make it faster than normal) and MySQL as these are pretty common technologies I’m likely to use (I may later play with nodejs and other databases, but for now a standard PHP/MySQL set up is fine). Type (all on one line):

sudo apt-get install nginx php5-fpm php5-curl php5-gd php5-cli php5-mcrypt php5-mysql php-apc mysql-server

Wait while all of these are set up. Follow any prompts that appear – yes you do want to set a password for the MySQL root user, choose one and remember it.

sudo nano /etc/nginx/nginx.conf

As I use the new Raspberry Pi 2 B with 4 cores, I don’t need to change that setting in the worker_processes. If you have the dual core, change the value from 4 to 2.

Inside the http { … } block we want to un-comment the ‘server_tokens off’ line;

Enabling this line stops nginx from reporting which version it is to browsers; which helps to stop people from learning your nginx version and then Googling for exploits they might be able to use to hack you.

Put a # in front of line: keepalive_timeout: 65;. We we’ll add our own one in a bit.

#keepalive_timeout   65;

We’re also going to add some lines under the Gzip section. Gzip compresses the files before they are sent over the network; which means a faster transfer. Gzipping them does take a bit of time as the Pi will have to zip them all before it sends them. Usually it’s a good trade off and ends up with a faster responding website. You can experiment with this on and off to see which is better for you. You want that section to look like this:

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

gzip_min_length   1100;
gzip_vary         on;
gzip_proxied      any;
gzip_buffers      16 8k;
gzip_comp_level   6;
gzip_http_version 1.1;
gzip_types        text/plain text/css applciation/json application/x-javascript text/xml application/xml 
                  application/rss+xml text/javascript images/svg+xml application/x-font-ttf font/opentype 
                  application/vnd.ms-fontobject;

We’re telling nginx to only Gzip files above a certain size, setting some buffers, and telling it which filetypes to Gzip. We’re also setting how compressed to be in gzip_comp_level. It accepts values from 1 to 9; 1 is the least compressed but fastest to compute. 9 is the most compressed but slowest to compute. With the Pi being a low power CPU I’ve chosen a middle-ground value of 6. We’ll also harden nginx against DDOS attacks a little bit by setting some more values. Add these somewhere inside the http block:

client_header_timeout 10;
client_body_timeout   10;
keepalive_timeout     10 10;
send_timeout          10;

All we’re doing here is limiting the amount of time nginx will wait for client connections. Keeping these short means that it’s a bit harder to flood nginx into a state of unresponsiveness. Hit Ctrl + X to exit, save your changes. We also need to set a few sane defaults for nginx when we want to use PHP with it. Enabling PHP support is not a global change, instead we can enable nginx to use PHP for specific virtual hosts, or even for specific directories within a specific virtual host. To set up some nice defaults we can import into virtual hosts as we go, type:

sudo nano /etc/nginx/fastcgi_params

Now, make sure your block looks just like the one below (which is taken directly from the official nginx wiki article)

fastcgi_param   QUERY_STRING            $query_string;
fastcgi_param   REQUEST_METHOD          $request_method;
fastcgi_param   CONTENT_TYPE            $content_type;
fastcgi_param   CONTENT_LENGTH          $content_length;

fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
fastcgi_param   PATH_INFO               $fastcgi_path_info;
fastcgi_param   REQUEST_URI             $request_uri;
fastcgi_param   DOCUMENT_URI            $document_uri;
fastcgi_param   DOCUMENT_ROOT           $document_root;
fastcgi_param   SERVER_PROTOCOL         $server_protocol;

fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR             $remote_addr;
fastcgi_param   REMOTE_PORT             $remote_port;
fastcgi_param   SERVER_ADDR             $server_addr;
fastcgi_param   SERVER_PORT             $server_port;
fastcgi_param   SERVER_NAME             $server_name;

fastcgi_param   HTTPS                   $https;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS         200;

Setting up PHP

The default settings for PHP will work fine and it’s already pretty well optimised (it even uses Unix sockets rather than TCP to communicate with nginx), but from a security standpoint we can ensure that PHP’s FPM module will only listen to nginx (and therefore is less likely to be hacked) by typing:

sudo nano /etc/php5/fpm/pool.d/www.conf

And un-commenting the lines listen.owner and listen.group. Save and exit the file.

Securing MySQL

MySQL ships with a few conveniences that are supposed to be removed when put on a real server, to do that type:

sudo mysql_secure_installation

Carefully read all the prompts and answer them.