Deploy with Ansible on CI/CD
By: Ahmet Türkmen
Tags: Deployment, Ansible, Github Actions, DevOps, Github

In this post, deployment process of an application with Ansible will be explained. Traditionally applications can be deployed in different ways, quite similar approach to deploy applications like in Ansible is executing bash script which has ssh commands. To give an example, Travis continuous integration has a feature where a bash script can be defined to deploy application and through given instructions within bash script, application can be successfully deployed.

Details regarding to deployment using Travis bash scripting can be found here

Travis Script Deployment

I would like to give an real case example from one of the project which I work on. We were using Travis script deployment for a while and it works pretty well. The bash script which I use in our deployment process is given below:

#!/usr/bin/env bash

f=dist/hknd_linux_amd64/hknd

amigo=./svcs/amigo

user=ntpd

hostname=sec02.lab.es.aau.dk

keyfile=./travis_deploy_key

deploy_path=/data/home/ntpd/daemon/hknd

amigo_path=/data/home/ntpd/daemon/svcs/amigo



if [ -f $f ]; then

echo "Deploying '$f' to '$hostname'"

chmod 600 $keyfile

ssh -i $keyfile -o StrictHostKeyChecking=no $user@$hostname sudo /bin/systemctl stop hknd.service

scp -i $keyfile -o StrictHostKeyChecking=no $f $user@$hostname:$deploy_path

scp -i $keyfile -r -o StrictHostKeyChecking=no $amigo $user@$hostname:$amigo_path

ssh -i $keyfile -o StrictHostKeyChecking=no $user@$hostname sudo /bin/systemctl start hknd.service

else

echo "Error: $f does not exist"

exit 1

fi

As you can observe from the bash script, every step of the deployment is given as ssh/scp commands. There is no harm regarding to it as long as it contains few steps. However, as time pass more configurations, applications will required to be deployed, updated, modified and checked, then it might turn into headache. Therefore, having well structured deployment steps using Ansible will put us to safe side.

Before jumping into deployment with Ansible, I would like to point out some factors which can be counted as disadvantages of not integrating Ansible to deployment process.

Not common way of utilizing resources

Not well structured deployment scripts which has high potential of being not working very well.

Having plain ssh commands increase likelihood of having issues regarding to settings, deployments and more.

There are many more drawbacks of using pure bash scripts in deployment process, however, these issues may not be applicable for all them.

For our case, I would like to convert our bash script given above to Ansible which has more elegant structure and easy to manage.

Move to Ansible

Since the bash script does not contain complex instructions, it would be very easy to convert it into Ansible playbooks. Before starting to convert it into Ansible playbook, necessary ssh connection should be set correctly for development and production environments. (- test environment as well if required -).

Setting ssh connection between server and ansible user is pretty straitforward, it contains following steps;

Generate SSH Key pair

Copy public key to authorized_keys on server side

on server side Encrypt private key

Have decrypt script to use private key on CI without compromising it.

Overall simplified flow for deployment is given below :

As it is declared from overall picture above, we need to provide encrypted ssh key and script for decryption together, in order to use plain private key to access the server.

In this setup, Github CI will be control node which will have access to server where we would like to deploy the application.

Let’s start to complete steps,

Generate SSH Key pair

$ ssh-keygen

You can keep everything default or provide some information about the questions when you run it. Once, execution of command finished, there will be public and private key, you need to append the public key to user’ authorized keys file on server. Afterwards, connection should be established, you may want to test it using traditional ssh command.

Encrypt Private Key

In order to use the ssh key which is generated before, we need to encrypt the key, I preferred to use gpg tool, there are many examples about it on internet, you can check it if you wish.

$ gpg --symmetric --cipher-algo AES256 <private-key-file>

The command will prompt you to provide passphrase to encrpyt and decrypt the private key when required. Choose strong and long passphrase. Once it is done, include encrpyted file into git. (- which means commit it as well-)

Once they have completed, the rest is structing Ansible playbook to deploy the file to server.