Ansible is a configuration management tool that system administrators use to automate infrastructure management activities.
Ansible uses only SSH to run commands remotely, and thus does not need an agent on the remote server. This makes Ansible preferable over other popular tools like Puppet or Chef when you don’t want to install agents on the managed servers.
Moreover, it is much easier to get started with Ansible because it uses YAML (Yet Another Markup Language) which is simpler than the more powerful programming languages that other tools use.
Drupal is a popular CMS whose installation is time-consuming, but easy to automate. In this tutorial, we are going to create an Ansible Playbook that automates the installation and configuration of Drupal and all its dependencies on systems that run Ubuntu 14.04.
You will need the following:
Ansible is not available in the default repositories that apt-get
uses. Therefore, add the repository ppa:rquillo/ansible
.
sudo add-apt-repository ppa:rquillo/ansible
Press ENTER when prompted.
Update the package lists.
sudo apt-get update
Install Ansible.
sudo apt-get install ansible
Ansible’s instruction sets are called playbooks. It’s a good idea to store all your playbooks in a single directory. Create a directory named MyPlaybooks.
mkdir ~/MyPlaybooks
Let us name our playbook drupal_setup
. Create a new directory named drupal_setup
.
mkdir ~/MyPlaybooks/drupal_setup
Each playbook usually has a hosts
file that contains names of the servers that it should use.
In this tutorial, we are going to install Drupal on localhost and one other server, drupal_server. You are free to add more servers to this file. Remember, every server you add should be accessible over SSH.
Use nano to create and edit a file named hosts
.
nano ~/MyPlaybooks/drupal_setup/hosts
Let it have the following contents:
[drupal_hosts]
localhost
drupal_server_ip
You should replace drupal_server_ip with your second server’s IP address. You can list as many IP addresses here as you want; you can use this playbook to install Drupal on any number of Ubuntu 14.04 servers.
Note: The
hosts
file is the file you should update if you want to reuse this playbook in the future to configure more Drupal servers. Note that you should remove the already-configured servers from the list, and add your new server IPs, before you re-run the playbook.
Save and close the file.
Create a new directory to store all the roles of the Playbook.
mkdir ~/MyPlaybooks/drupal_setup/roles
We need to apt-get
update the servers before doing anything else, so create a directory for the role update
.
mkdir ~/MyPlaybooks/drupal_setup/roles/update
Each role has one or more tasks. Create a directory named tasks
to hold all tasks associated with this role.
mkdir ~/MyPlaybooks/drupal_setup/roles/update/tasks
Use nano
to create and edit a new task file named main.yml
. This is the file that tells Ansible what to do when it executes this role.
nano ~/MyPlaybooks/drupal_setup/roles/update/tasks/main.yml
In this file, use Ansible’s apt
module to update the system:
---
- name: apt-get update the server
apt: update_cache=yes
Make sure your file doesn’t have any extra whitespace; Ansible is picky about this. Save and close the file.
Create a directory for the role php.
mkdir ~/MyPlaybooks/drupal_setup/roles/php
Create the tasks
directory for this role:
mkdir ~/MyPlaybooks/drupal_setup/roles/php/tasks
Drupal needs a web server which is configured to use PHP. In this tutorial, we use Apache. When we install PHP, Apache is installed automatically, so we don’t need any extra commands for it.
Use nano to create and edit the main.yml
for the php role.
nano ~/MyPlaybooks/drupal_setup/roles/php/tasks/main.yml
Use Ansible’s apt
module to install PHP5 (and the packages it depends on), and the PHP5 GD library. Add the following to the file:
---
- name: Install PHP and associated packages
apt: name=php5 state=latest
- name: Install PHP GD library
apt: name=php5-gd state=latest
notify:
- Restart Apache
Apache has to be restarted after the PHP GD library is installed. Therefore, this role also needs a handler.
All handlers of a role are stored in a separate directory. Create a directory named handlers
for the current role.
mkdir ~/MyPlaybooks/drupal_setup/roles/php/handlers
Use nano to create and edit the main.yml
file.
nano ~/MyPlaybooks/drupal_setup/roles/php/handlers/main.yml
Add the following code to it:
---
- name: Restart Apache
service: name=apache2 state=restarted
You’re done with the PHP and Apache setup.
Drupal needs a database to store settings and content. In this tutorial, we use MySQL.
Create directories for this role and its tasks.
mkdir -p ~/MyPlaybooks/drupal_setup/roles/mysql/tasks
The first task of this role installs MySQL and its dependencies. Use nano to create and edit a file named setup.yml
.
nano ~/MyPlaybooks/drupal_setup/roles/mysql/tasks/setup.yml
In this file, we will tell Ansible to use the apt
module again to install:
So, add the following to the file:
---
- name: Install MySQL server
apt: name=mysql-server state=latest
- name: Install Apache module for MySQL authentication
apt: name=libapache2-mod-auth-mysql state=latest
- name: Install MySQL module for PHP
apt: name=php5-mysql state=latest
Our role has one more tasks file. As Drupal needs its own MySQL database and database user, we will create a separate tasks file to create them. Use nano to create and edit a file named create_db.yml
.
nano ~/MyPlaybooks/drupal_setup/roles/mysql/tasks/create_db.yml
Ansible has modules that let you manage MySQL. In this task, we will use the following modules:
mysql_db
- To create a new database for Drupal.mysql_user
To create a new user and allow it to access the database.Before we use mysql_db
or mysql_user
we should make sure that the Python MySQLdb
package is installed on the remote host. Use the apt
module to install it.
Add the following contents to the file:
---
- name: Install Python MySQLdb
apt: name=python-mysqldb state=latest
- name: Create the Drupal database
mysql_db: db={{ db_name }} state=present
- name: Create the Drupal user
mysql_user: >
name={{ db_user }}
password={{ db_password }}
priv={{ db_name }}.*:ALL
host=localhost
Note that strings enclosed in {{ }} denote variables. In this task, we have the variables {{ db_user }}
, {{ db_password}}
and {{ db_name }}
. We are going to set the values of these variables in a later step.
Next, we need to let Ansible know that this role has two tasks. To do this, we create a main.yml
file.
nano ~/MyPlaybooks/drupal_setup/roles/mysql/tasks/main.yml
Add the following code to this file:
---
- include: setup.yml
- include: create_db.yml
It’s now time to move on to the installation of Drupal itself.
Create directories for this role and its tasks.
mkdir -p ~/MyPlaybooks/drupal_setup/roles/drupal/tasks
Use nano to create and edit a task file named main.yml
.
nano ~/MyPlaybooks/drupal_setup/roles/drupal/tasks/main.yml
In this task, we will tell Ansible to perform the following actions:
git
on the remote host. This is necessary because we will be using Ansible’s git
modulegit
module to clone the latest stable version of Drupal from its repository at http://git.drupal.org/project/drupal.git
. The downloaded files are placed in /var/www/html/drupal
settings.php
and services.yml
files from the default filessettings.php
, services.yml
, and sites/default/files
Add the following code to the file:
---
- name: Install git
apt: name=git state=latest
- name: Clone Drupal
git: >
repo=http://git.drupal.org/project/drupal.git
dest=/var/www/html/drupal/
update=no
- name: Create settings.php
command: cp /var/www/html/drupal/sites/default/default.settings.php /var/www/html/drupal/sites/default/settings.php
- name: Create services.yml
command: cp /var/www/html/drupal/sites/default/default.services.yml /var/www/html/drupal/sites/default/services.yml
- name: Update permissions of settings.php
file: path=/var/www/html/drupal/sites/default/settings.php mode=777
- name: Update permissions of services.yml
file: path=/var/www/html/drupal/sites/default/services.yml mode=777
- name: Update permissions of files directory
file: >
path=/var/www/html/drupal/sites/default/files
mode=777
state=directory
recurse=yes
You’ll want to update the permissions for these files later after completing the browser installations on each server (on each server, rather than through Ansible).
At this point, all our roles are ready. We now need to use them.
Use nano to create a file named site.yml
. This is the file we will actually run with Ansible.
nano ~/MyPlaybooks/drupal_setup/site.yml
In this file we perform the following activities:
sudo
should be used to run all tasks of this PlaybookAdd the following code to it:
---
- hosts: drupal_hosts
sudo: yes
vars:
- db_name: drupal
- db_user: drupal_user
- db_password: drupal_db_pass
roles:
- update
- php
- mysql
- drupal
Make sure you change the value of the variable db_password
to something other than drupal_db_pass
. You are free to change the values of the other two variables as well to match your preferences.
Before you run the Playbook, your ~/.ssh/known_hosts
file should have an entry for each of the hosts mentioned in the hosts
file.
An easy way to do this is to connect once to each server listed in the ~/MyPlaybooks/drupal_setup/hosts
file from this server, using SSH.
Connect to localhost
via SSH using the command:
ssh localhost
If this is the first time you are connecting to the server this way, you will be prompted with a message that says:
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is b1:18:3d:19:15:21:39:5a:f7:9f:3c:37:68:ba:62:01.
Are you sure you want to continue connecting (yes/no)?
Once you say yes
, you will get a message saying:
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
Connect to any other servers listed in the hosts
file:
ssh drupal_sudo_user@drupal_server_ip
Make sure you replace the username and IP address with the actual information for each server. Please keep in mind that the sudo username (drupal_sudo_user
in the example) and password should be the same for each server, including localhost.
Note: Instead of using passwords, you could copy the SSH public key for the Ansible server’s sudo user to the
drupal_sudo_user's
authorized_keys
file on each managed server.
Once you have connected to each server, you are ready to run the playbook.
The Playbook is now ready to be tested. Fire it off using the ansible-playbook
command. The -k
option forces Ansible to ask for the SSH password, and is not necessary if you have set up passwordless authentication. The -K
option forces Ansible to ask for the sudo
password.
cd ~/MyPlaybooks/drupal_setup/
ansible-playbook -i hosts site.yml -kK
Enter the SSH password, and wait as the Playbook runs. Once the run completes, you’ll have a fresh Drupal installation on your server.
Note: You could leave out the
-k
flag if you have added the SSH key from the Ansible server’s sudo user to each managed server.
This will take a few minutes to run, and Ansible will show you what it is doing at each step.
Important: If you want to run this script to set up more servers in the future, you must remove the IP addresses of the servers that are already set up from the
~/MyPlaybooks/drupal_setup/hosts
file, or Ansible will overwrite your customized Drupal sites.
Now, you will be able to use a browser to access Drupal and complete the browser-based installation, at http://your_server_ip/drupal/
.
If you need help with completing the browser installer for Drupal, follow along with the instructions in this article.
Your database settings will be the variables you set in the vars
section of the ~/MyPlaybooks/drupal_setup/site.yml
file.
Double-check that each server has a successful Drupal installation.
Now’s a good time to remove the hosts from the ~/MyPlaybooks/drupal_setup/hosts
file. That way, if you run the playbook again, you won’t accidentally overwrite the hosts that you have already set up.
Note that YAML is whitespace-sensitive. If you are having trouble with your playbook, you probably have improper indentation or extra spaces in your .yml
files.
If you see an error that looks like:
fatal: [server-name] => Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host.
This means you missed adding an entry for one or more hosts in the ~/.ssh/known_hosts
file.
You’ll need to make a manual SSH connection to localhost
or to the target remote server first. Then try running the playbook again.
With this tutorial, you have learned to create an Ansible playbook that sets up Drupal for you, along with Apache and MySQL. Before you use this playbook in production systems, you will have to further build on it to make the installation more secure. You could also use Drush commands in the playbook to manage the Drupal installation.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
As an alternative to Ansible you can use Docker containers. Check out Wodby, it’s a Docker platform for Drupal. All you need is to connect Wodby to your DO account and create/import drupal site via UI.
Better to instal Ansible via python PIP.
Awesome guide. One note: ansible is available in trusty’s repositories (universe).
A newer version of ansible is in trusty-backports or the ppa mentioned. Cheers,
Nice guide.
Some comments/additions:
using ansible-galaxy to generate your role folders and their sub folders makes this way easier than creating each by hand… it can simply generate a role and all subfolders with a command like: $ ansible-galaxy init drupal or $ ansible-galaxy init mysql
This comment has been deleted