Deploying Drupal 8 using Ansible Playbook: Part 3

Drupal Role

Create a new directory for “drupal” role and subdirectories for tasks.

mkdir -p roles/drupal/tasks
nano roles/drupal/tasks/main.yaml
---
- name: install the latest Composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer warn=False
args:
creates: /usr/local/bin/composer
- name: install git
package: name=git state=latest
- name: clone Drush repository
git:
repo: https://github.com/drush-ops/drush.git
version: "9.3.0"
dest: /opt/drush
- name: install Drush dependencies with Composer
shell: composer install
args:
chdir: "/opt/drush"
- name: create the Drush executable link
file:
src: /opt/drush/drush
dest: /usr/local/bin/drush
state: link
- name: install mysql client
package: name=mysql-client state=present
- name: create the Drupal install directory
file:
path: "{{ drupal_site_path }}"
state: directory
- name: clone Drupal repository
git:
repo: http://git.drupal.org/project/drupal.git
version: "{{ drupal_version }}"
dest: "{{ drupal_site_path }}"
- name: install Drupal dependencies with Composer
shell: composer install
args:
chdir: "{{ drupal_site_path }}"
creates: "{{ drupal_site_path }}/vendor/autoload.php"
- name: install Drupal
shell: drush si -y --site-name="{{ drupal_site_name }}" --account-name={{ drupal_admin_username }} --account-pass="{{ drupal_admin_pass }}" --db-url=mysql://{{ drupal_db_user }}:{{ drupal_db_pass }}@{{ hostvars['db-server']['ansible_default_ipv4']['address'] }}/{{ drupal_db_name }}
args:
chdir: "{{ drupal_site_path }}"
- name: set proper ownership
file:
path: "{{ drupal_site_path }}"
owner: www-data
group: www-data
recurse: yes
- name: set permissions on the settings file
file:
path: "{{ drupal_site_path }}/sites/default/settings.php"
mode: 0744
- name: set permissions on files direcotry
file:
path: "{{ drupal_site_path }}/sites/default/files"
mode: 0777
state: directory
recurse: yes
nano group_vars/all.yaml
# Drupal Variablesdrupal_version: 8.5.3
drupal_site_path: "/var/www/drupal"
drupal_site_name: "My Drupal Site"
drupal_admin_username: admin
drupal_admin_pass: StrongPass

NGINX Role

Our Drupal website is now installed, but we will need to install NGINX web-server to expose the Drupal site to the internet. The last role “nginx” in our Ansible playbook will install the NGINX web-server along with optional SSL support by let’s encrypt CA. The user can set the variable to true to generate the let’s encrypt certificate in the global variables file. If the SSL cert is generated, then we will configure Drupal to be accessed from the domain name. Else, the Drupal site will be accessed from the IP address of the “web-server” instance.

mkdir -p roles/nginx/{tasks,handlers,templates}
nano roles/nginx/tasks/main.yaml
---
- name: remove Apache web server
package: name=apache2 state=absent

- name: install nginx web server
package: name=nginx state=present
- name: add the certbot repository
apt_repository: repo='ppa:certbot/certbot' state=present update_cache=yes
when:
- letsencrypt_generate == true
- letsencrypt_domain is defined
- letsencrypt_email is defined
- name: install certbot
package: name=python-certbot-nginx state=latest update_cache=yes
when:
- letsencrypt_generate == true
- letsencrypt_domain is defined
- letsencrypt_email is defined
- name: start and enable nginx service
service: name=nginx state=started enabled=yes
- name: generate letsencrypt certificates
shell: certbot certonly --nginx -d {{ letsencrypt_domain }} -n --agree-tos -m {{ letsencrypt_email }}
args:
creates: /etc/letsencrypt/live/{{ letsencrypt_domain }}
when:
- letsencrypt_generate == true
- letsencrypt_domain is defined
- letsencrypt_email is defined
- name: remove default nginx configuration
file: name=/etc/nginx/sites-enabled/default state=absent
notify:
- restart nginx
- name: generate a new configuration for Drupal
template:
src: drupal.conf
dest: /etc/nginx/sites-enabled/drupal.conf
owner: www-data
group: www-data
notify:
- restart nginx
- name: configure the certbot cronjob
cron:
name: letsencrypt_renewal
special_time: weekly
job: /usr/bin/certbot renew --post-hook "systemctl reload nginx"
when:
- letsencrypt_generate == true
- letsencrypt_domain is defined
- letsencrypt_email is defined
- meta: flush_handlers
nano group_vars/all.yaml
# Let's Encrypt Settings# Set it to false if domain is not configured.
letsencrypt_generate: true
letsencrypt_domain: mydrupal.example.com
letsencrypt_email: me@example.com
nano roles/nginx/handlers/main.yaml
---
- name: restart nginx
service: name=nginx state=restarted
nano roles/nginx/templates/drupal.conf
{% if letsencrypt_generate and letsencrypt_domain is defined and letsencrypt_email is defined %}
server {
listen 80 default_server;
server_name {{ letsencrypt_domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 default_server;
server_name {{ letsencrypt_domain }};
ssl_certificate /etc/letsencrypt/live/{{ letsencrypt_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ letsencrypt_domain }}/privkey.pem;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
{% endif %}
{% if not letsencrypt_generate %}
server {
listen 80 default_server;
{% endif %}
root {{ drupal_site_path }}; access_log /var/log/nginx/drupal.access.log;
error_log /var/log/nginx/drupal.error.log;
gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/html text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6].(?!.*SV1)";
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ \..*/.*\.php$ {
return 403;
}
location ~ ^/sites/.*/private/ {
return 403;
}
location ~ (^|/)\. {
return 403;
}
location / {
try_files $uri /index.php?$query_string; # For Drupal >= 7
}
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
location ~ '\.php$|^/update.php' {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
include fastcgi_params;
include snippets/fastcgi-php.conf;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
location ~ ^/sites/.*/files/styles/ { # For Drpal >= 7
try_files $uri @rewrite;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
drupal-ansible/
├── ansible.cfg
├── group_vars
│ └── all.yaml
├── hosts
├── playbook.yaml
└── roles
├── drupal
│ └── tasks
│ └── main.yaml
├── mariadb
│ ├── handlers
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ └── templates
│ └── my.cnf
├── nginx
│ ├── handlers
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ └── templates
│ └── drupal.conf
└── php
└── tasks
└── main.yaml
14 directories, 12 files

Running the Playbook

Now that everything is created, run the playbook and let Ansible do the Drupal installation for you.

ansible-playbook playbook.yaml
aliyun@ubuntu:~/drupal-ansible$ ansible-playbook playbook.yaml PLAY [all] ***************************************************************************************************TASK [Gathering Facts] ***************************************************************************************
ok: [web-server]
ok: [db-server]
TASK [update and upgrade system packages] ********************************************************************...TASK [nginx : configure the certbot cronjob] *****************************************************************
changed: [web-server]
RUNNING HANDLER [nginx : restart nginx] **********************************************************************
changed: [web-server]
PLAY RECAP ***************************************************************************************************
db-server : ok=6 changed=12 unreachable=0 failed=0
web-server : ok=18 changed=24 unreachable=0 failed=0

Conclusion

In this detailed tutorial, we have learned how to use Ansible by creating a playbook to install Drupal on Ubuntu 16.04. Ansible is a great tool for configuration management due to its simplicity. Adoption is very easy with Ansible, far easier than writing a bash script. It can be used in any use case where repetition is required. Ansible follows the concept of idempotency. Idempotency is doing only necessary changes without side effects. For example, when you install a package using a playbook. On the first run, Ansible will install the package for you. But on the second run of the same playbook, Ansible will just verify if the package is installed. If it is installed, Ansible will just skip the job without reinstalling the package.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com