Use Ansible to automate installation and deployment of Raspberry boxes

Roberto Pozzi
8 min readApr 11, 2020

Whenever you repeat an action more than twice, or when you need to do anything that requires coordination of many tasks, you should consider to put some automation in place.

In previous articles I described how to use a Raspberry Pi box as a Web Server and deploy a simple web application (you can find the link here) and how to secure it using SSL certificates (you can read it here).

Even these relatively simple tasks require many steps for web server installation and configuration, and application build and deployment; in this article I will go one step beyond and explain how you can use Ansible (https://www.ansible.com/) to fully automate all these processes.

At the end of this article you should be able to:

  • Install Ansible on your workstation;
  • Get a basic understanding of how Ansible works (basic configuration, managed hosts, playbooks for task automation);
  • Write a relatively simple Ansible playbook;
  • Use an Ansible playbook to install Apache and OpenSSL on a Raspberry Pi and deploy an application to Apache.

Before you start

To demonstrate Ansible automation capabilities I developed a simple application based on Angular (https://angular.io/) along with some useful scripts and Ansible playbooks; I put all the code in a couple of GitHub repositories, so if you want to follow the instructions step by step be sure to setup your environment appropriately and meet all the prerequisites, i.e.:

  • Raspberry Pi is installed and ssh is configured in order to connect from your workstation (you can refer to my tutorial here if you need help);
  • Git is installed: you can find the instructions to install it for different platforms at the link here;
  • Angular is installed: follow the instructions at the link here to setup Angular and all its prerequisites.

The stack I use for my home development is the following:

  • Raspberry Pi 4 Model B Rev 1.2, with Raspbian GNU/Linux 10 (buster);
  • Mac Book with macOS 10.14.5 as my development workstation.

I am pretty sure this should work smoothly on any other MacOs or Linux based system and on different Raspberry Pi boards but the stack above is the only one I actually tested.

If you are ready, let’s start our journey.

Setup Ansible on your workstation

Ansible (https://www.ansible.com/) is a very convenient and widely used open source tool for automation and configuration management. It is very simple because it does not need any complex infrastructure to setup (you can easily install it on your workstation) and is agent-less, meaning it does not require any component to be installed on the managed servers, Ansible will just use SSH to connect and manage them.

Before installing Ansible, you should setup SSH keys, which will be used by Ansible to automate and run tasks on remote systems, I wrote a short article on what you need and how to do it, you can read it here.

Install Ansible on your workstation

You will find detailed instructions on how to install Ansible on your workstation for different Operating Systems at this link https://docs.ansible.com/ansible/latest/index.html, just choose your platform.

As an example, these are the few easy commands to install Ansible on MacOs:

cd $HOME
curl https://bootstrap.pypa.io/get-pip.py -0 get-pip.py
sudo python get-pip.py
sudo pipo install ansible

Use Ansible playbook for Raspberry Pi automation

Once Ansible is installed, let’s use it to automate software installation and configuration on Raspberry. Start by cloning my GitHub repository, with the following commands:

cd $HOME
git clone https://github.com/robipozzi/windfire-raspberry.git
cd windfire-raspberry

Ansible configuration settings

Ansible configuration can be done in different ways, in the repository cloned above you will find a file, called ansible.cfg, if you launch Ansible from that directory this file will be read and used as the source for configuration settings (unless you have set an ANSIBLE_CONFIG environment variable, which has precedence), the basic configuration you should have is something like this:

Figure 1 — Ansible configuration file

where:

  • private_key_file points to the SSH private key you have previously generated, used by Ansible to connect and launch tasks on the target Raspberry Pi box, change it according to your environment;
  • inventory defines where Ansible will look for the inventory file, which is used by Ansible to know which servers to connect and manage.

Ansible inventory settings

If you do not have it already, create the /etc/ansible/hosts inventory file with the following commands:

sudo mkdir /etc/ansible
sudo vi /etc/ansible/hosts

Your inventory file should look like the following (where 192.168.1.119 is the IP of my Raspberry, change it to match yours):

[raspberry]
192.168.1.119

The heading in brackets is a logical group name, which is used to classify hosts and decide what hosts you are controlling at what times and for what purpose. In my case I have only one Raspberry to manage but I could have multiple and by just listing all the Raspberries in the inventory under the [raspberry] section, Ansible will run the same automation tasks on all of them consistently, cool isn’t it?

Anatomy of an Ansible playbook: install Apache2 on Raspberry Pi

Once we have setup the few basic configurations above, now it comes the real magic: and the magic is all in the playbook.

Simply put, Ansible playbooks are files that declare configurations and orchestrate the ordered execution of the steps in a process, even spanning between sets of different machines in particular orders. They can launch tasks synchronously or asynchronously.

The example in my GitHub repository will clarify better: in the root folder you will find the playbook raspberry.yaml, let’s see how it is structured.

Figure 2 — Ansible playbook hosts section

In the figure above you can see the initial section of the playbook, made of the following parameters:

  • hosts: raspberry defines the machine set (named raspberry in this example) to which the configuration and the steps below (see Figure 3) will be applied. Remember how we configured the /etc/ansible/hosts file with the [raspberry] heading? Do you notice anything? Exactly: the headings match!! It means this playbook will apply to all the machines defined in /etc/ansible/hosts file under [raspberry] heading;
  • remote_user: {{ user }} defines the user that will run the commands defined in the playbook. The {{ user }} notation is just the way you can reference variables within a playbook;
  • become: yes sets privilege escalation. The become keyword leverages existing privilege escalation tools like sudo, allowing to run with root privileges;
  • vars section sets the variables that can then be reused through out the playbook. The {{ playbook_dir }} in the example represents the path to the directory of the playbook. It is a so called “magic” variable (i.e.: a variable that cannot be set directly by the user but is set by Ansible to reflect internal state);
  • vars_files section references one or more files that define variables.

Then it comes the tasks section, where you define what the playbook actually does and which commands are run on the target systems.

Figure 3 — Ansible playbook tasks section

In my raspberry.yaml playbook you will find several tasks, each having a similar structure, let’s analyze the one named Install Apache2 as an example.

I gave it a name, Install Apache2 (which should be quite self explanatory) and it uses apt module to run an apt-get command on Raspberry.

Modules are discrete units of code that can be used in playbook tasks. Ansible executes each module, usually on the remote target machine, and collects return values. Each module supports taking different arguments (here you can find an exhaustive list of available modules and how they can be configured).

In my case I configured apt module with 2 parameters:

  • name: it is the name of the package that will be installed with apt-get, in this case apache2;
  • state: indicates the desired package state, in this case present, meaning the output of the tasks should be having the package installed on the target system.

We have all that we need, so let’s unleash Ansible automation by running the following command, which will apply all the configurations and run all the steps defined in raspberry.yaml playbook:

ansible-playbook raspberry.yaml

Now open your browser, point to your Raspberry Pi IP (something like http://192.168.1.119) and, if everything is ok, you will see Apache2 home page below, that means Ansible has done its job and has installed Apache2 on your Raspberry Pi for you !!!

Figure 4 — Apache home page

Use an Ansible playbook to deploy an application

Now that we have automated Apache2 installation, let’s take a step further and deploy a simple application to it.

Clone my GitHub repository by launching the following commands:

cd $HOME
git clone https://github.com/robipozzi/windfire-restaurants-ui.git
cd windfire-restaurants-ui

The repo holds the code of a simple Angular application I developed for the purpose of testing; do not expect anything fancy, it just returns a list of restaurants from a mock service. Initialize Angular dependencies by launching the following utility script:

./app-init.sh

In the root folder find and launch deploy.sh script, just like this:

./deploy.sh

select option 1. Raspberry -with restaurants mockup, the script will start and do the following things:

  1. it compiles Angular application and put them into dist/ output directory using ng build --configuration=mockup command;
  2. it runs the deploy.yaml playbook in deployment/raspberry sub-folder to deploy the application, using the following ansible-playbook command: ansible-playbook deployment/raspberry/deploy.yaml;
  3. it removes dist/ output directory.

The playbook will do the following steps:

  1. it copies Angular application files from your workstation to a remote folder on Raspberry Pi, using Ansible copy module;
  2. it removes all files from Apache2 document folder /var/www/html, using Ansible file module;
  3. it copies Angular application files to /var/www/html, using Ansible shell module;
  4. it removes all files .

Open your browser at http://<PUT_YOUR_RASPBERRY_IP_HERE> and you will see something like:

Figure 5 — Application Home page

Congratulations!! You just successfully used Ansible to fully automate all the deployment steps of the application.

Conclusion

In this article we have seen how easy is to work with Ansible and Raspberry and how to:

  • Install Ansible on your workstation;
  • Setup Raspberry Pi to be managed by Ansible;
  • Write and run an Ansible playbook that automates Apache2 installation on Raspberry Pi;
  • Write and run an Ansible playbook that automates deployment of an application to Raspberry Pi.

I hope you had fun reading through this article, found it useful and got some idea to use Ansible and Raspberry for your own work. There is much much more to Ansible than what I just wrote in this tutorial, in the References section you will find links to the full documentation.

Perfection is not a steady state but is a journey that never ends so, as always, I invite you to report any mistake or give me any suggestion for enhancement.

References

In the writing of this article I used and referred to a bunch of other sites, which I report and leave here for reference:

--

--

Roberto Pozzi

Roberto works as Cloud Architect, specialized in cloud native and container based architectures.