Tutorials

How to use Ansible for setting up a Raspberry Pi Zero W Web Server with PHP 7

Introduction

The Raspberry Pi Zero W is a small (and affordable) computer on a board – it has the essentials for creating little projects with built-in wi-fi, an HDMI output and an extra USB for input from a keyboard or mouse. It runs a Linux distribution (Raspbian) and for that reason it’s very versatile and user-friendly, since we can use pretty much any programming language that can run on Linux. Apart from that, of course, you have the GPIO pin head to create circuits and use components to make your project really smart.

Now, not everybody realizes the extent of what you can do with this little board. With the right software and optimized settings, you can serve a whole “full-stack” application, literally! You can work with bare metal components and high-level APIs using your favorite programming language. How cool is that?

As a demonstration, we’re gonna build a portable PHP 7 web server, but what’s more: we’re gonna automate most of the dirty work using a configuration management tool – Ansible. This will make the whole work easily reproducible, so you can even create multiple applications in separate micro SD cards to switch as you like.

This tutorial shows how to automate most of the work for setting up a PHP 7 web server on a Raspberry Pi Zero W running Raspbian. We are going to use Ansible for automation.

In case you never heard of Ansible before, this tutorial I wrote for the DO community can help you get started quickly:  Configuration Management 101: Writing Ansible Playbooks .

Requirements

  • Raspberry Pi Zero W – It must be running a recent version of Raspbian, and you must be able to connect to it via SSH. If you are just getting started, have a look at our detailed setup guide for Raspberry Pi Zero W, and come back here when you are able to connect to your Pi via SSH from your dev machine.

Please note that the controller machine (your dev machine in this case) must be running Linux (or Mac OS), since Ansible does not support Windows (as controller machine) and neither do I 😛

Installing Ansible

Please refer to the official documentation for a comprehensive set of instructions on how to install Ansible on your operating system. If you already have a recent version of Ansible installed, proceed to the next step.

Getting the raspi-ansible files

To save you a lot of work, I shared the whole setup I made here (just a couple roles, playbooks and the right settings) to have it all up and running after two commands – mind you that each one will take some time to run, but at the end you should have your PHP 7 web server ready to serve.

The files are available in this Github repository: codingmamalabs/raspi-ansible . Have a look there if you want to check the files beforehand.

Clone the repository somewhere on your dev machine:

git clone https://github.com/codingmamalabs/raspi-ansible.git

Now follow the steps to set up and run Ansible on your Raspi Zero.

Step 1: Set Up Connectivity

The first thing we need to do is to set up connectivity and prepare for the first Ansible run. Since this is a new Raspbian install, it has the default user and password ( u: pi / p: raspberry ) that comes with all fresh installs. We will use these for the SSH setup in the next step.

But first of all, you’ll need to edit the inventory file (a file named hosts in the project’s root directory) and change the IP address there to reflect your Raspberry Pi Zero W IP address. The inventory file contains, as the name suggests, the inventory of servers to be controlled by Ansible. This is how our inventory file looks like:

[raspi01]
192.168.0.27

[webservers:children]
raspi01

Change 192.168.0.27 to the IP address of your Raspberry Pi Zero W. After changing that information, let’s run Ansible to execute an ad-hoc command to test connectivity and show information about your Raspberry Pi Zero:

ansible webservers -k -m setup

Quick explanation of each item in this command:

  • ansible  the Ansible executable, used for running ad-hoc commands on one or multiple hosts
  • webservers  the subgroup of servers in which I want to execute the command
  • -k  ask for SSH password (depends on sshpass)
  • -m setup run the specified module: setup. This is the module to show the server facts.

Use the password raspberry. After a few seconds it should print a big json containing all the facts collected by Ansible. Example output (excerpt):

192.168.0.27 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.0.27"
        ], 
        "ansible_all_ipv6_addresses": [
            "fd00:f0f2:4990:a2:3d6e:857e:cafe:681", 
            "fe80::f745:81d2:91a6:55a2"
        ], 
        "ansible_architecture": "armv6l", 
        "ansible_bios_date": "NA", 
        "ansible_bios_version": "NA", 
        "ansible_cmdline": {
            "8250.nr_uarts": "0", 

If you got an error, maybe you need to install sshpass in order to be able to provide a password for Ansible. Check the error message to see if that’s the case.

If you already have sshpass installed and the error is something else, try adding -vvvv to make the command extra verbose.

If you got the output, it means connectivity is fine, and Ansible is capable of running commands on your Raspberry system. You can go ahead to the next step.

Step 2: Run the Setup Playbook

We are going to run a playbook this time. It has a few tasks to configure the server and it will copy your current user public key as authorized key for the user pi inside the Raspberry, so you can log in simply by running ssh pi@your-pi-address , no need for passwords. This will also facilitate running Ansible in the future, to avoid having to provide the password all the time! This playbook also disables GUI for optimization, since our Raspberry will be used as a server only*. Below you can find the contents of the setup playbook:

---
- hosts: all
  become: true
  vars:
  sys_packages: [ 'wget', 'vim', 'git']
  roles:
  - piconfig

*You can enable the GUI again whenever you want from the command-line configuration tool raspi-config

This playbook will execute the role piconfig on all hosts from the inventory. The variable sys_packages is used to define which extra system packages you would like to install. To check the contents of the role piconfig, please have a look at the raspi-ansible repository.

Run the following command to execute the setup playbook (again, it will ask for the SSH password, which by default is raspberry):

ansible-playbook -k setup.yml

The following output is expected:

SSH password: 

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [192.168.0.27]

TASK [piconfig : Update apt] ***************************************************
ok: [192.168.0.27]

TASK [piconfig : Install System Packages] **************************************
changed: [192.168.0.27] => (item=[u'wget', u'vim', u'git'])

TASK [piconfig : Set authorized key took from file] ****************************
changed: [192.168.0.27]

TASK [piconfig : Disable GUI] **************************************************
changed: [192.168.0.27]

RUNNING HANDLER [piconfig : stop lightdm] **************************************
changed: [192.168.0.27]

PLAY RECAP *********************************************************************
192.168.0.27               : ok=6    changed=4    unreachable=0    failed=0   

After this playbook is executed, you should be able to connect via SSH to the Raspberry Pi and also run Ansible commands without the need to provide a password. To test it out, run the same command from the previous step, now without the -k argument:

ansible webservers -m setup

You should see the same output from the first run, except that this time it won’t ask for a password.

Step 3: Run the Web server Playbook

The webserver.yml playbook will install PHP 7 and PHP7-fpm, as well as Nginx:

---
- hosts: webservers
  become: true
  vars:
  doc_root: /var/www
  server_name: "{{ ansible_wlan0.ipv4.address }}"
  dev_packages: [ 'curl','php7.0-curl', 'php7.0-cli' ]
  roles:
    - nginxphp

This playbook will execute the nginxphp role on the subgroup “webservers” of our inventory.  It sets a few variables necessary for the role to be executed. To have a look at the contents of the nginxphp role, please check the raspi-ansible repository.

Run the following command to execute the web server playbook:

ansible-playbook webserver.yml

This is the expected output:

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [192.168.0.27]

TASK [nginxphp : Install Nginx] ************************************************
changed: [192.168.0.27]

TASK [nginxphp : Install php7.0-fpm] *******************************************
changed: [192.168.0.27]

TASK [nginxphp : Change default nginx site] ************************************
changed: [192.168.0.27]

TASK [nginxphp : Install DEV Packages] *****************************************
changed: [192.168.0.27] => (item=[u'curl', u'php7.0-curl', u'php7.0-cli'])

TASK [nginxphp : Set up Demo Page] *********************************************
changed: [192.168.0.27]

RUNNING HANDLER [nginxphp : restart nginx] *************************************
changed: [192.168.0.27]

PLAY RECAP *********************************************************************
192.168.0.27               : ok=7    changed=6    unreachable=0    failed=0   

After this playbook run is finished, you should have a working PHP 7 web server running on your Raspberry Pi Zero W. Go to your browser and point it to the Rasp Pi address, you should see something like this:

 

Congrats! Now, to spice things up, what about creating a little LED circuit to test your Raspberry Pi Zero W GPIO? Check out our tutorial: LED blinking on Raspberry Pi Zero (hint: you can use PHP for controlling the LED!)

Remember that to make it a real portable web server, you need to use a portable power source. This works quite well:

A Portable Web Server (PHP7) setup with Raspberry Pi Zero W

Troubleshooting

If you get any Ansible errors, add -vvvv to the command to increase verbosity. This will help a lot!

UPDATE 30/05/2018: PHP 7.1

This tutorial shows how to manually update from PHP 7.0 to PHP 7.1. I might include the option to install PHP 7.1 in the Ansible setup, however since it involves a system upgrade on Raspbian it shouldn’t be the default option at the moment.

Liked it? Take a second to support erikaheidi on Patreon!

1 thought on “How to use Ansible for setting up a Raspberry Pi Zero W Web Server with PHP 7”

Leave a Reply

Your email address will not be published. Required fields are marked *