Raspberry Pi Dev Setup with Nginx + PHP7

How to develop Grav sites with a $35 computer

12 mins

Last year I setup a Raspberry Pi 2 Model B as a development web server. I took note of the steps involved and over the ensuing months, I've provided those notes to individuals on our Gitter chat looking to do the same thing. I recently purchased the latest Raspberry Pi 3 Model B which has the same form-factor, but has a faster 1.2Ghz quad core processor, built-in WIFI, and Bluetooth 4.1. I thought I would take this opportunity to update my notes, and turn them into a full blown tutorial as this seems to be a popular subject.

In this tutorial, we cover the basics to get Raspbian OS running on your Raspberry Pi computer. We will install the high-performance nginx 1.9 webserver, along with PHP 7.0 for optimal performance. We'll also cover installing the latest Netatalk 3 with spotlight support for easy file sharing with your Mac. So read on dear listener if you would like to discover the joy of building your own full linux-powered server on a $35 computer!

Initial Raspbian Installation

Raspbian is the best option for operating systems on the Raspberry Pi because it's the most supported and is based on Debian, a very popular Linux distribution. Those of you that have used Debian or Ubuntu will be very much at home with Raspbian. The current version called Jessie is equivalent to the latest Debian 8 release.

Rather than rehashing all the information available, I suggest you follow the installation procedures outlined on the Raspberry Pi site and install NOOBS onto an SD card. After you have created your bootable NOOBS installer, you can insert it in your Raspberry Pi and power it on. It will boot very quickly and then you can simply pick Raspbian from the installer and let it do it's thing.

When the installation is complete, you should be greeted by a clean desktop environment. Time to get some things setup and configured!

Raspbian Updates

Throughout this tutorial, I'm going to assume you are using a terminal so if you have not already done so, start up a terminal by clicking the terminal icon from the top menu bar of the desktop and it will launch a terminal instance for you.

Even though you just installed Raspbian, there are often updates to packages available so the first thing to do is make sure you are running the latest versions. Follow these steps:

$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get upgrade

You probably won't have any extra updates to perform after the dist-upgrade step, but better safe than sorry!

Raspbian Configuration

We can use the RASPI Config command to setup some important configuration options for our new Pi.

$ sudo raspi-config

Read the official docs for full details, but I like to set the following:

  • Change Password - pick a new unique password (default is raspberry)
  • Boot Option - I like to select console as I don't use the desktop at all
  • Internationalisation Options - Change Locale to suite (I use en_US.UTF-8), Change Timezone to UTC (why?)

Choose your Editor

By default Raspbian comes with the GNU Nano Editor. It's a very capable editor and is great for newbies because it has on-screen help for commands. However, I've been a Vi kind of guy for many years, and just feel more comfortable using that. Vi has been around for years, and Vim is a new and improved version that is easily installable on Raspbian:

$ sudo apt-get install vim

Throughtout this guide I commonly will have vi commands for editing files. You can simply replace this with nano if you wish to use the default editor.

Changing the default Hostname

By default, Raspbian installs with the hostname raspberry. If you wish to change this to something more memorable, you just need to edit this value and then restart the hostname service:

$ sudo vi /etc/hosts
$ sudo vi /etc/hostname
$ sudo /etc/init.d/hostname.sh

Accessing Remotely

It's all well and good to use your new Raspberry Pi machine via the keyboard and monitor you have plugged into it, but it's much easier to simply access it remotely from your regular desktop. To do this your best friend is SSH (Secure Shell). In order to reach your Raspberry Pi, you will need to know the IP address. To do so simply type:

$ hostname -I

This will report the current IP address of the machine.

On your regular computer, you can simply create a /etc/hosts entry with this IP and a suitable name. Usually this should match the hostname you just set. Then you can access your Pi remotely via:

$ ssh pi@raspberry

Enter the password you set in the configuration step, or if you have not set the password yet, it will be raspberry. More details can be found in the docs.

It is strongly advised to use SSH Keys rather than passwords. There is a great tutorial on how to set up Passwordless SSH Access in the offical docs.

Updating Firmware (Optional)

Your Raspbian installation also included a pretty recent copy of the Raspberry Pi firmware. However, sometimes there are important updates, so it really doesn't hurt to update this to the latest version:

$ sudo rpi-update
$ sudo reboot

Change the Shell (Optional)

By default, Raspbian ships with the very capable bash shell. However, I personally prefer zsh which has many useful features. On top of this I like to use Oh My ZSH! which is a handy ZSH configuration tool that comes packed with custom plugins, themes, etc.

To install this just follow these steps:

$ sudo apt-get install zsh
$ wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh
$ chsh -s `which zsh`

Then simply log out and back in to see your new shell in all it's glory! I like to change the theme to nice clean multi-line version. To do so simply edit the ~/.zshrc file and change the theme to one of the many supported themes (I personally like candy).

Install PHP 7.0

Raspbian being based on Debian Jessie ships with PHP 5.6 by default. This works fine, but there is a better option and that is PHP 7.0. Released in December of 2015, PHP 7.0 is a radical jump forwards for PHP in terms of performance, language features and reduction in memory usage.

As with most PHP-centric projects, Grav commonly sees 2X performance increases when running under PHP 7.0 and that combined with the reduction in memory, makes it an ideal candidate for the Raspberry Pi.

To install this newer PHP version however, we must tap into the testing branch of Raspbian, commonly known by the codename stretch. We must edit the sources.list file used by Aptitude (apt-get):

$ sudo vi /etc/apt/sources.list

Add this line under the first jessie line:

deb http://mirrordirector.raspbian.org/raspbian/ stretch main contrib non-free rpi

Now, by adding this all installs or updates will default to use the newer versions of files available in the stretch release which is not considered 100% stable. The way around this is to pin all packages to use the jessie release with a higher priority by default. To do this create a preferences file:

$ sudo vi /etc/apt/preferences

And paste in the follwing:

Package: *
Pin: release n=jessie
Pin-Priority: 600

Save this file and update:

$ sudo apt-get update

You can see which release versions are available with which priority by using sudo apt-cache policy. You can also see specific versions of packages with sudo apt-cache policy <package_name>

Now you are ready to install PHP 7.0 from the stretch release including all the common PHP packages:

$ sudo apt-get install -t stretch php7.0 php7.0-curl php7.0-gd php7.0-fpm php7.0-cli php7.0-opcache php7.0-mbstring php7.0-xml php7.0-zip

Notice the use of -t stretch to specify the release? This is not strictly necessary as php7.0 packages do not exist in the jessie release, but again, better to be specific here.

After this has been completed, you can quickly test to make sure things have been installed by simply typing:

$ php -v
PHP 7.0.4-7 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

Installation of nginx 1.9

While it's trivial to install nginx 1.6 with Raspbian, we want to use a faster, more up to date, and secure version of nginx here, and luckily there's a nginx 1.9 version available in the stretch release.

$ sudo apt-get install -t stretch nginx

You can easily see what version would install by simulating an install: sudo apt-get install -t stretch -s

Once installed, we want to modify our PHP 7.0 FPM pool to use our pi user and group, so edit the config file:

$ sudo vi /etc/php/7.0/fpm/pool.d/www.conf

And and change the user and group references:

user = pi
group = pi

Next we want to create a new nginx configuration for our grav test site:

$ sudo vi /etc/nginx/sites-available/grav

In this file paste:

server {
    #listen 80;
    index index.html index.php;

    ## Begin - Server Info
    root /home/pi/www/grav;
    server_name localhost;
    ## End - Server Info

    ## Begin - Index
    # for subfolders, simply adjust:
    # `location /subfolder {`
    # and the rewrite to use `/subfolder/index.php`
    location / {
        try_files $uri $uri/ /index.html /index.php;
    }
    ## End - Index

    ## Begin - PHP
    location ~ \.php$ {
        # Choose either a socket or TCP/IP address
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        # fastcgi_pass 127.0.0.1:9000;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
    ## End - PHP

    ## Begin - Security
    # deny all direct access for these folders
    location ~* /(.git|cache|bin|logs|backups|tests)/.*$ { return 403; }
    # deny running scripts inside core system folders
    location ~* /(system|vendor)/.*\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny running scripts inside user folder
    location ~* /user/.*\.(txt|md|yaml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny access to specific files in the root folder
    location ~ /(LICENSE.txt|composer.lock|composer.json|nginx.conf|web.config|htaccess.txt|\.htaccess) { return 403; }
    ## End - Security
}

Now we need to ensure the default site is not loaded and we load this new grav site instead:

$ cd /etc/nginx/sites-enabled/
$ rm default
$ ln -s ../sites-available/grav

Then simply restart nginx and php-fpm to ensure the new changes are picked up:

$ sudo /etc/init.d/nginx restart
$ sudo /etc/init.d/php7.0-fpm restart

Installing Grav

The nginx configuration is expecting our Grav site to be located in /home/pi/www/grav, so now we need to create that folder structure:

$ cd ~;mkdir www;cd www

Then download Grav release package you wish to install. We are going to use the Blog Skeleton in our example, but you can use any release package or skeleton:

$ wget https://github.com/getgrav/grav-skeleton-blog-site/releases/download/1.1.1/grav-skeleton-blog-site-v1.1.1.zip
$ unzip grav-skeleton-blog-site-v1.1.1.zip
$ mv grav-skeleton-blog-site grav

Adjust the naming of the these files to reflect the Grav release package or skeleton you are using

At this point, and if you followed all the steps properly, you should be able to point your browser at your Raspberry Pi with either the IP or the hostname you setup in your /etc/hosts file. For example: http://raspberry.

Problems?

If you have a problem reaching the webserver, there are a few things to check:

  1. You have a symbolic link called grav in your /etc/nginx/sites-enabled folder
  2. The grav file looks correct and matches the example pasted above
  3. If you receive a 'Bad Gateway' error, then check to ensure the /var/run/php/php7.0-fpm.sock file exists and is referenced correctly in the /etc/nginx/sites-available/grav file.

Advanced - Install Netatalk 3 (Optional)

Now you have a 100% functional Linux server that is perfect for web development. However, it's more convenient to be able to access your new server with a shared network folder from your main development machine. If you are using a Mac like I am, then you are going to want to install Netatalk 3 which is a Linux implementation of the Apple AFP network protocol. The problem however, is that by default Raspbian (even the stretch release) only provides a very old version that doesn't work well with modern versions of OS X.

If you are using a Windows machine, you will need to install Samba rather than Netatalk, but this is a pretty straightforward process that has been documented elsewhere.

The solution is to download the source of the latest Netatalk 3 server software, and build it for your Raspbery Pi. Perform the following steps:

$ sudo apt-get install libdb-dev libevent-dev libssl-dev libgcrypt11-dev libkrb5-dev libpam0g-dev libwrap0-dev libtdb-dev libmysqlclient-dev avahi-daemon libavahi-client-dev libacl1-dev libldap2-dev libcrack2-dev libldap2-dev systemtap-sdt-dev libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-dev
$ cd ~;mkdir src;cd src
$ wget wget http://downloads.sourceforge.net/project/netatalk/netatalk/3.1.8/netatalk-3.1.8.tar.bz2
$ tar -xvf netatalk-3.1.8.tar.bz2; cd netatalk-3.1.8
$ ./configure \
        --with-init-style=debian-sysv \
        --without-libevent \
        --without-tdb \
        --with-cracklib \
        --enable-krbV-uam \
        --with-pam-confdir=/etc/pam.d \
        --with-dbus-sysconf-dir=/etc/dbus-1/system.d \
        --with-tracker-pkgconfig-version=1.0
$ make
$ sudo make install

Assuming everying built correctly you need to edit the configuration file:

$ sudo vi /usr/local/etc/afp.conf

Modify the existing file with the following content:

;
; Netatalk 3.x configuration file
;

[Global]
; Global server settings

[Homes]
        basedir regex = /home

; [My AFP Volume]
; path = /path/to/volume

After this point you should be good to go to restart the service:

$ sudo /etc/init.d/netatalk restart

Now you should see your server show up in the sidebar of Finder. Simply connect with your pi user and password.

FYI, you can validate that things are setup correctly by typing:

$ sudo /usr/local/sbin/afpd -V

You should see output similar to the following:

afpd 3.1.8 - Apple Filing Protocol (AFP) daemon of Netatalk

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version. Please see the file COPYING for further information and details.

afpd has been compiled with support for these features:

          AFP versions: 2.2 3.0 3.1 3.2 3.3 3.4
         CNID backends: dbd last tdb mysql
      Zeroconf support: Avahi
  TCP wrappers support: Yes
         Quota support: Yes
   Admin group support: Yes
    Valid shell checks: Yes
      cracklib support: Yes
            EA support: ad | sys
           ACL support: Yes
          LDAP support: Yes
         D-Bus support: Yes
     Spotlight support: Yes
         DTrace probes: Yes

              afp.conf: /usr/local/etc/afp.conf
           extmap.conf: /usr/local/etc/extmap.conf
       state directory: /usr/local/var/netatalk/
    afp_signature.conf: /usr/local/var/netatalk/afp_signature.conf
      afp_voluuid.conf: /usr/local/var/netatalk/afp_voluuid.conf
       UAM search path: /usr/local/lib/netatalk//
  Server messages path: /usr/local/var/netatalk/msg/