Skip to main content
Deployment

Deployments with Ansible and Ansistrano

original photo by Elliott Plack

Having researched website deployment options recently, both Ansible and Ansistrano make a compelling argument for their adoption, so I jumped in with both feet and am glad I did.

With special thanks to Oliver Davies in England, who recorded a strong presentation of his Dransible code, which I merely forked for my own purposes. The name Dransible is a mash-up of Drupal and Ansible. 

And while it may seem like a strange word, the name Ansistrano makes sense, combining Ansible and Capistrano. Capistrano is a legacy deployment tool coded in Ruby. Ansistrano replicates the Capistrano process, having been rewritten in Ansible, and the result is a delight to use.

A major feature of Ansible is how simple it is to script a deployment using only ssh, with no software dependencies on target servers.

Oliver's Dransible code requires Vagrant, which I swapped out with Ubuntu LTS servers hosted publicly on the internet replacing it. My idea/plan was, (and still is?), to automatically initiate a deployment for every GIT commit pushed to a GitLab server. GitLab allows Ansible scripts to kick-off a splendid idempotent Continuous Integration process.

My idea/plan was also to make the source code for this website public, just like some US Federal  and EU websites, however Oliver Davies' use of Ansible vault to obfuscate sensitive website information is incompatible with GitLab CI at this time. The problem is, GitLab can't run automatically unless the password to unencrypt the obfuscated data is stored in plaintext, in the same GIT repository. That obviously breaks any notion of security. However what still works well in this workflow, for me anyway, is Oliver's use of rsync between my local workstation and the public server in the cloud. Oliver Davies wrote to me with a secure solution! I'll implement it ASAP to incorporate GitHub/GitLab CI and update this page when I do.

I've added a script which takes place at the very end of the Ansistrano deployment. This script uploads a recent copy of the local website database I use along with everything in sites/default/files to common Shared directory. Now a deployment is only a ~3 minute, one-click background process.

Ansistrano saves x number of deployments, while also doing garbage collection, and it is easy to rollback to any of them. Plus as far as I am concerned, the public website is 'disposable' in the sense it can easily be rebuilt from scratch using local Drupal sources and scripts.

Instructions

There's no need to write down details Oliver Davies has already covered in his presentation. I have documented how my forked source-socde differs from Oliver Davies' Dransible code. The source-code I forked is at Github. Copy the ansible folder to your website project root, so the ansible folder is at the same level, and just outside of your Drupal web root.

Key variables to adjust

hosts.yml:
server.example.com  # <-- server hostname 

requirements.yml:
These versions should be up-to-date. Refer to these URLs to see what the latest version is:

vars/vars.yml:
fully_qualified_domain_name:  example.com  # <-- website hostname
project_source_path: /path/to/website/project/root/  # The trailing slash is critical!

vars/deploy_vars.yml:
trusted_hosts:
           - '^example\.com$'

ansible.cfg:
remote_user = username

Decrypt/Encrypt the vaults

Ensure the text within vault-password.txt is accurate, then use the following examples.

ansible-vault encrypt deploy_vault.yml
ansible-vault decrypt provision_vault.yml

My fork of Oliver Davies' code also uses the same three commands.

Download Requirements

Run this once, to download relevant dependencies to your where your deployment scripts are. As time passes, this coded list becomes out of date, so you may need to manually refresh and test it.

ansible-galaxy install -r requirements.yml

Provision a new server

My fork was tested using Digital Ocean and VULTR cloud hosts using Ubuntu LTS server. Once your server is available to use, login as root and update it:

apt update

apt upgrade

apt autoremove

Next, create a new user and set a password:

useradd username

passwd username

Add the new user to the sudo and www-data groups:

usermod -a -G sudo username

usermod -a -G www-data username

reboot

It might make sense to add those commands to the beginning of the provision script below in the future.

Run this once, to install a new server from scratch after a few manual steps have been performed. 

ansible-playbook tools/ansible/provision.yml

This is not required but at this point, I also installed webmin for convenience on the remote server manually as I otherwise found no Ansible role to include webmin with into the provision script:

wget https://www.webmin.com/download/deb/webmin-current.deb

dpkg -i webmin_2.013_all.deb   # <- Yours may be newer.

Deploy a new website

Before you can deploy the website, you must run this command from your Drupal project root folder to download the database you want to upload in the subsequent step, (don't change the database name, so the database can sync up later):

drush sql-dump> databasebackup.sql

Having done that, run this final script to update the public server with the local Drupal website. 

ansible-playbook tools/ansible/deploy.yml

References

 Easy web deployments with Ansistrano 

How to use GitLab and Ansible to create infrastructure as code

VideoJS Media block module has been released

old time movie projector

Read more...

Closed-source vs open-source website hosting

We use open-source software

Read more...

Fork an upstream GIT repository and make it your own

Fork an upstream GIT repository

Read more...

VPN/DNS: Pihole - Wireguard - Unbound installation

Here's a recipe for your pie hole

Read more...