Community Blog Deploying Drupal 8 using Ansible Playbook: Part 1

Deploying Drupal 8 using Ansible Playbook: Part 1

In this multi-part article series, we will be deploying Drupal 8 using Ansible Playbook on an Alibaba Cloud Elastic Compute Service (ECS) instance.

By Liptan Biswas, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

Ansible is an open source IT automation software. Ansible can be used to automate processes such as application deployments, intra-service orchestration, and cloud provisioning. Ansible is very easy to deploy as it does not require any additional agent or software on the nodes; it uses SSH to connect to the other instances.

Ansible uses YAML to illustrate the jobs or plays in a text file. YAML is very popular language to write a configuration file and is also very easy to use. Ansible is way simpler than its alternatives such as Chef or Puppet.

In this three-part tutorial, we will be deploying Drupal 8 using Ansible Playbook on an Alibaba Cloud Elastic Compute Service (ECS) instance. Specifically, we will learn more about writing a modular playbook for Ansible. Each group of tasks will be separated by a specific role in our playbook. In the first part of the tutorial, we will be looking at creating our project and overriding the default Ansible behavior. In the second part of the tutorial, we will write the plays into roles. In the last part of the tutorial, we'll be executing the playbook using Ansible after writing the remaining roles.


  • Two Alibaba Cloud ECS instances with Ubuntu 16.04 64-bit installed. You can follow this Quick Start Guide to create the instances. Let's call the first instance as "web-server" and assume the public IP assigned to the server is "". We will use this server to install Drupal using Drush on NGINX with PHP 7.2. Similarly, we will call our second server as "db-server" having public IP "". We will install MariaDB server on this instance to host the Drupal database. Make sure to use SSH Key based authentication rather than password authentication and use the same key for both the instance.
  • Important: Firewall or Security group rules configured to allow the port "80", "443" for everyone from the "web-server" instance. For the database server, you will only need to allow access to the private IP address of the "web-server" instance on port "3306".

This tutorial assumes that you have already created both the instance and configured SSH key-based authentication on the instances with the same key. Here are the goals which we will accomplish using Ansible:

  1. Install the MariaDB server and create the database for Drupal on the instance named "db-server".
  2. Install the PHP 7.2 on the instance "web-server".
  3. Clone the Drupal 8 and Drush 9 Github repository and install Drupal on the instance "web-server".
  4. Install the NGINX Web server to host the Drupal site with optional Let's Encrypt SSL on the instance "web-server".

Getting Started with Ansible

It is not required to install Ansible on either of the instances which we will manage using the Ansible. However, installation of the Ansible is required on your local workstation from which you are planning to manage the instances. If you want, you can also use a server on Alibaba Cloud to manage other nodes. If you are using a Linux Ubuntu desktop or server, you can follow the instructions on the tutorial, How to install Ansible on Ubuntu 16.04.

Installation of Ansible on other platforms such as CentOS, Windows, and MacOS is also easy but is out of the scope of the tutorial. Just install the latest version of Python 2.7 and run the command pip install ansible from the Python command line as pip is installed by default in latest Python. All the commands in the tutorial are written for Ubuntu 16.04. It may work on other Linux distros as well.

In this tutorial, I will assume that you have already installed Ansible on your local computer. You can verify if Ansible is installed on your local computer by running the ansible --version command. You should see a similar output.

aliyun@ubuntu:~$ ansible --version
ansible 2.5.4
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/aliyun/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.15rc1 (default, Apr 15 2018, 21:51:34) [GCC 7.3.0]

Create a new project directory in which we will store everything related to our project, the playbooks, roles, and other files throughout the tutorial.

mkdir ~/drupal-ansible

Switch to the newly created directory.

cd ~/drupal-ansible

By default, Ansible uses the host file located at "/etc/ansible/hosts" to find the instances to connect to. This host file should contain the list of all the servers we want to manage. Ansible configuration can be overridden locally for each project by placing a file with the name ansible.cfg at the root of the project directory. Create a new local Ansible configuration file.

nano ansible.cfg

Populate the file with the following configuration.

inventory = hosts
host_key_checking = false
private_key_file = ~/.ssh/aliyun.pem

Let's go through the configuration supplied in the above file. The line inventory = hosts tells Ansible to use the file named hosts for the list of instances to manage rather than the default one. Setting host_key_checking to false will disable the host key checking and you will not get prompted to verify the host keys which you usually get on the first SSH connection to the instance.

Replace the value of private_key_file with the path of your actual private key which you will use to connect to the instances. In my case, I have put the private key at ~/.ssh/aliyun.pem. If you have the SSH agent running, holding the private key for authentication, you can omit this configuration. It is very important to secure and safeguard the private key. Make sure that you have set "400" or read-only permission on the key. Anyone having access to the private key will have full access to your ECS instances. Save the file ansible.cfg and exit from the editor.

Now that our configuration file is in place, let's create the host file which will contain all the nodes we want to manage with Ansible. Create a new hosts file using the following command.

nano hosts

Populate the file with the following configuration. Make sure to replace the example IP addresses with the actual ones.

web-server  ansible_ssh_host= ansible_ssh_user=root
db-server  ansible_ssh_host= ansible_ssh_user=root


In the above "hosts" file, you can see we have two nodes in place. The first node is named as "web-server" and is reachable on the address "". ansible_ssh_user specifies the user with which Ansible will log in to the instance and will use that user for running the commands. Similarly, we have the second node named "db-server" on which we will install MariaDB server.

Finally, [all:vars] group is used to define the variables for all the hosts in all groups. Ansible is written in Python and it uses the Python interpreter to execute tasks on the remote machine. Ubuntu 16.04 instances come with Python 3 pre-installed, which is available on /usr/bin/python3 but cannot be invoked directly. That is why we need to explicitly specify the Python binary to use when working with Ubuntu 16.04 instances. Save the hosts file and exit the editor.

Before we proceed further to create the roles and tasks, let's verify if Ansible can reach our hosts by running the command ansible all -m ping. You should see a similar message if the execution is successful.

aliyun@ubuntu:~/drupal-ansible$ ansible all -m ping
db-server | SUCCESS => {
    "changed": false, 
    "ping": "pong"
web-server | SUCCESS => {
    "changed": false, 
    "ping": "pong"

Now that we know that Ansible can successfully connect to the instances, let start creating the Ansible playbook file. This Ansible playbook file will be used by the "ansible-playbook" command to run the plays.

cd ~/drupal-ansible
nano playbook.yaml

Populate the file with the following YAML code. Make sure to use correct spacing and indentation. Ansible uses two spaces for each indentation.

- hosts: all
  gather_facts: true
  - name: update and upgrade system packages
      upgrade: yes
      update_cache: yes

- hosts: db-server
    - mariadb

- hosts: web-server
  become: true
    - php
    - drupal
    - nginx

Let's go through the code above. Notice that we have used three dashes --- at the start of the file. These dashes are optional and define the start of a document in YAML syntax. - hosts defines the instances on which the followed tasks and roles are needed to be executed. For example, the tasks in the first block of the code will be executed on all the instances described in the inventory. The task will update the repository cache and the installed packages in the system.

For writing complex playbooks in Ansible, we can break a playbook into multiple files called roles. Each role is modular, reusable and fully independent collections of variables, tasks, files, templates, and modules. Roles are not playbooks but are collections of tasks which are limited to achieving a particular functionality. In this tutorial, we will also break our playbook into four various roles.

  1. mariadb: It will add MariaDB repository into the system and will install the latest version of MariaDB server. Furthermore, it will also install the MySQL client for Python and then it will create the database and the database user for Drupal.
  2. php: This role will add the PPA for PHP 7.2 and then install PHP 7.2 along with the required modules.
  3. drupal: This role will install the latest version of Composer and Git. It will clone the Drush and Drupal repository and will install the dependencies using Composer. Finally, it will install Drupal with the help of Drush.
  4. nginx: This role will install NGINX web-server and configure it to host the Drupal site. If a domain name is provided, it will also install Certbot and generate and install the SSL certificates automatically.

Once all our systems are updated, we want to proceed to the installation of MariaDB. Notice that on the next block, we have only provided the "db-server" in the hosts. Thus, the tasks in the "mariadb" role will be executed only on the "db-server" host.

Similarly, we will run the roles "php", "drupal", and "nginx" on the server named "web-server".


In this tutorial, we have learned the basics of the Ansible and how Ansible playbook is created. We have learned to override the Ansible configuration file as well as using a local host file to define the hosts on per project basis. Finally, we created the playbook file which will run all the plays or tasks that we will define in the different roles in the next tutorials.

In the next tutorial of this series, we will be creating the different roles that will contain the tasks or plays to be executed on remote machines.

0 0 0
Share on

Alibaba Clouder

2,600 posts | 751 followers

You may also like