Ansible Playbooks

Ansible is a tool used to automate software provisioning, configuration management, and application deployment. It offers several advantages over other IT automation tools similar to it; It's minimal in nature, you don't need to install anything on the servers you're deploying to (except Python 2).

The most atomic of components in Ansible is a task. A task can be viewed as a codified action. This could, for instance, be a codified action to make sure file A is copied to location B on the server Ansible is running against. More formally the Ansible documentation defines a task as "a call to an ansible module". In the example above, the call will be to the copy module.

To easily manage (deploy new instances of or update) your OpenSRP, Keycloak, OpenMRS, and DHIS2 servers you would require Ansible to automate the deployment process.  Therefore the opensrp-playbooks provided here are meant to facilitate the process. All you need to do is clone the opensrp-playboks repository and then define your inventories based on your DevOps clients and development environments(staging, production or preview) and then run the playbooks to install the servers. The repository uses Ansible's recommended alternative directory layout.

For local "dev" deployments, you will need to install Virtualbox. You'll as well need the vault password used to encrypt sensitive info inside the sample inventory available in the repo. You will also need to create host_vars and group_vars to match your setup.

Deploying OpenSRP, keycloak, DHIS2, OpenMRS on a local virtual machine (VM)

NOTE: The following steps work when you want to test deploying opensrp, keyloak, dhis2 and openmrs servers on a virtualbox host for purposes of testing locally.

Setting up virtual machine

You can setup a virtual machine by the following ways.

  • Virtualbox:

            Opensrp support Ubuntu 16.04 to 18.04. You can download Ubuntu 18.04 image from this site Ubuntu 18.04 image and set it up on your virtual machine or virtualbox.

  1. Create an sudo user (user with admin rights) called ubuntu and ensure that the user has NOPASSWD config on the `/etc/sudoers` (you can refer to the command used below on Vagrant #3).

  2. On the host you have to install openssh-server to enable ssh connections and make it possible to ssh using the root account otherwise you will need an account with administrative privileges to run the playbooks.

    On Ubuntu or any debian disto you can install it using this command

    1 $ sudo apt install openssh-server

     

  3. Finally ensure you can access the server though ssh ubuntu@vm-ip-address (You can get the vm-ip-address of the VM by running ifconfig on the host terminal). If it requests for password kindly disable it by

    1 2 $ sudo sed -i 's/prohibit-password/yes/' /etc/ssh/sshd_config $ sudo service ssh restart
  • Vagrant: 

    Vagrant is a tool for building and managing virtual machine environments in a single workflow. You can download it from hereBelow is a Vagrantfile that can get you up and running.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.box = "hashicorp/bionic64" config.vm.network "private_network", ip: "192.168.33.13" #replace with any private ip available config.vm.provision "shell", inline: <<-SHELL apt-get update apt-get install -y cloud-init python3 python3-psycopg2 useradd -s /bin/bash -m -p $(openssl passwd -1 <specify-password-for-ubuntu-user>) ubuntu #1 usermod -s /bin/bash -aG sudo ubuntu #2 sudo sed -i -e '$a\\ubuntu ALL=(ALL) NOPASSWD:ALL' /etc/sudoers #3 SHELL end

NOTE:
Ansible communicates with hosts via SSH. Thus you have to generate a private and public ssh key then copy the public key to the host(s)  by

1 $ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@vm-ip-address

or login to the server and add your ssh key.

If you do not have the ssh keys you can generate one by running the below first:

1 $ ssh-keygen -t rsa -b 4096 -C "<your_email_address>" 

Setting up Development Environment

Now that you have setup your virtual machines we will need to setup the development environment

  1. Git clone the opensrp-playbooks from this link OpenSrp playbooks. Then switch directory to opensrp-playbooks you just cloned.

    1 $ git clone --recursive git@github.com:opensrp/playbooks.git && cd playbooks
  2. Setup a python virtual environment:

    1. Kindly follow the steps here

    2. Create a virtual environment called opensrp.

    3. Switch to opensrp environment by typing:

      1. 1 $ workon opensrp
      2. Add the following line to the end of ~/.bashrc of your machine ... Ensure you update <python-version> with version of python running on you machine.

        1. 1 export ANSIBLE_STRATEGY_PLUGINS=~/.virtualenvs/opensrp/lib/python<python-version>/site-packages/ansible_mitogen/plugins/strategy #Update <python-version>
      3. Run the following command while on the virtual environment

        1. 1 $ python --version

          confirm that your active python version is 3

        2. 1 $ pip install -r requirements/base.pip
        3. 1 $ ansible-galaxy role install -r requirements/ansible-galaxy.yml -p ~/.ansible/roles/opensrp
        4. 1 $ ansible-galaxy collection install -r requirements/ansible-galaxy.yml -p ~/.ansible/collections/opensrp

          Opensrp-playbooks requires some modules from ansible-galaxy. The modules are specified in the requirements.yml file. Refer to this link for more information on ansible-galaxy : ansible-galaxy documentation

          You need to run the two commands above before running any playbooks to install the required modules..

  3. If you have not created the inventory yet kindly execute the commands below on the root of opensrp-playbooks directory.

    1. $ ./scripts/new_inventory.sh opensrp-app-servers demo staging

      1 $ ./scripts/new_inventory.sh opensrp-app-servers demo staging
    2. $ ./scripts/new_inventory.sh openmrs-app-servers demo staging (optional  if keycloak is used)

      1 $ ./scripts/new_inventory.sh openmrs-app-servers demo staging
    3. $ ./scripts/new_inventory.sh mysql demo staging

      1 $ ./scripts/new_inventory.sh mysql demo staging
    4. $ ./scripts/new_inventory.sh all demo staging

      1 $ ./scripts/new_inventory.sh all demo staging
    5. $ ./scripts/new_inventory.sh opensrp-redis-servers demo staging

      1 $ ./scripts/new_inventory.sh opensrp-redis-servers demo staging
    6. $ ./scripts/new_inventory.sh opensrp-postgresql-servers demo staging

      1 $ ./scripts/new_inventory.sh opensrp-postgresql-servers demo staging
    7. $ ./scripts/new_inventory.sh keycloak-app-servers demo staging (optional if openmrs is used)

      1 $ ./scripts/new_inventory.sh keycloak-app-servers demo staging
  4. Add the host_vars directory and hosts file from the following directory: sample-inventories/inventory-a

  5. Update the host_vars vars.yml file with your  VMs ip, as below:

    1. ansible_host: "<vm-ip-address>"

  6. Finally add files directory with a pgp directory containing gpg keys like so:

├── files
│   └── pgp
│   ├── <short-key-id>-priv.key
│   ├── <short-key-id>-pub.key
│   └── <short-key-id>-ultimate.trust

Follow the following tutorial to create gpg keys.

Ensure you have the following setup at the end of the above process:

inventories

├── demo
│   └── staging
│   ├── files
│   │   └── pgp
│   │   ├── <short-key-id>-priv.key
│   │   ├── <short-key-id>-pub.key
│   │   └── <short-key-id>-ultimate.trust
│   ├── group_vars
│   │   ├── all
│   │   │   └── vars.yml
│   │   ├── keycloak-app-servers
│   │   │   └── vars.yml
│   │   ├── mysql
│   │   │   └── vars.yml
│   │   ├── openmrs-app-servers
│   │   │   └── vars.yml
│   │   ├── opensrp-app-servers
│   │   │   └── vars.yml
│   │   ├── opensrp-postgresql-servers
│   │   │   └── vars.yml
│   │   └── opensrp-redis-servers
│   │   └── vars.yml
│   ├── hosts
│   └── host_vars
│   └── host1
│   └── vars.yml

 

WARNING!! JUST ENSURE YOU DO NOT COMMIT SENSITIVE INFORMATION ABOUT THE IMPLEMENTATION OF YOUR INFRASTRUCTURE WHEN DEFINING YOUR DEVOPS CLIENT(S) INSIDE THE INVENTORIES DIRECTORY.

host_vars directory where you define variables  that are specific to a particular host.

group_vars directory where you define variables  for all the hosts that are grouped together host.

You can read more about host_vars, group_vars and how to work with ansible inventories from here:  Working with inventories.

 

Inside host_vars there is a directory named host1 (can be renamed to any relevant name describing your host) . host1 contains two files vars.yml and vault.yml

var.yml - Has defined varibles for opensrp and openmrs. Because this file is inside host1 directory, the variables will only apply to this server/host.

vault.yml - Has encrypted sensitive information/secrets used in the vars.yml file. For the sample inventory the passwords and secrets are dummy for real implementation you would require serious passwords/keys.

Installing required modules and setting up server

Server setup

You will need the following on inventories/demo/staging/group_vars/all/vars.yml for your local stage setup

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 all_opensrp_postgres_superuser: "opensrp" # update this to opensrp instead of root from the default file server_monitoring_hostname: "vagrant" server_monitoring_set_hostname: true server_monitoring_hostname_from_ec2_Name_tag: false server_monitoring_graphite_server_ip: "127.0.0.1" server_monitoring_graphite_server_port: "2003" server_monitoring_graphite_server_protocol: "tcp" server_monitoring_owner: "ubuntu" server_monitoring_server_type: "staging" slack_monit_endpoint: "" all_gpg_key: "<short-key-id>" all_gpg_dir: "inventories/demo/staging/files/pgp" gpg_private_key: "{{ all_gpg_dir }}/{{ all_gpg_key }}-priv.key" gpg_public_key: "{{ all_gpg_dir }}/{{ all_gpg_key }}-pub.key" gpg_trust_file: "{{ all_gpg_dir }}/{{ all_gpg_key }}-ultimate.trust" nginx_install_only: true

Run the following to setup the server.

1 $ ansible-playbook -i inventories/demo/staging setup-server.yml --vault-password-file=[local path to the file holding the vault password]  --skip-tag nginx,certbot

OpenMRS (for opensrp server web v2.1.*)

You will need the following for you local stage setup

on inventories/demo/staging/group_vars/openmrs-app-servers/vars.yml

1 2 openmrs_tomcat_version: 9 tomcat_group: "tomcat"

if you have a domain update this

1 openmrs_site_name: ""

on inventories/demo/staging/group_vars/mysql/vars.yml

1 mysql_backup_gpg_dir: "{{ all_gpg_dir }}"

Run the following command to start the OpenMRS playbook in your local staging environment:

1 $ ansible-playbook -i inventories/demo/staging deploy-openmrs.yml --vault-password-file=[local path to the file holding the vault password] --skip-tag nginx,certbot,collectd

Keycloak (for opensrp server web v2.2.* and above)

Run the following command to start the keycloak playbook in your local staging environment: (ensure keycloak-app-servers is in your hosts file )

1 $ ansible-playbook -i inventories/demo/staging deploy-keycloak.yml --vault-password-file=[local path to the file holding the vault password] --skip-tag nginx

OpenSRP

You will need the following for you local stage setup:

on inventories/demo/staging/group_vars/opensrp-app-servers/vars.yml

1 2 3 4 opensrp_install_swap: false # update with the opensrp version tag/branch you need to deploy opensrp_version: "v2.1"

if you have a domain update this variable

1 opensrp_site_name: ""

 

1 2 3 4 5 # for opensrp_version version v2.2 you have to add the below opensrp_maven_package_profiles: - postgres - jedis - oauth2
1 2 3 4 5 # keycloak configs opensrp_keycloak_realm: "realm" opensrp_keycloak_auth_server_url: "http://keycloak.local/auth/" opensrp_keycloak_client: "resource-id" opensrp_keycloak_client_secret: "234324"

on inventories/demo/staging/group_vars/opensrp-postgresql-servers/vars.yml

1 2 3 opensrp_postgres_enable_ssl: false postgresql_enable_ssl: false postgresql_backup_enabled: false

In opensrp we have spring maven profiles, kindly enable the ones you need:

The defaults are:

- postgres
- jedis
- basic_auth # this can be replaced with oauth2 to use keycloak or spring authentication server with openmrs

The other available profiles are openmrs-sync, dhis2-sync, rabbitmq, rapidpro, lettuce, dhis2-sync-vaccine-tracker and more

To use openmrs one has to use v2.1* tags.

Run the following command to start the OpenSRP playbook in your local staging environment:

1 $ ansible-playbook -i inventories/demo/staging deploy-opensrp.yml --vault-password-file=[local path to the file holding the vault password]  --skip-tag nginx,certbot,collectd

DHIS 2

Run the following command to start the DHIS playbook in your local staging environment:

1 $ ansible-playbook -i inventories/demo/staging deploy-dhis.yml --vault-password-file=[local path to the file holding the vault password] --skip-tag nginx,certbot

NOTE

When running the playbooks with a user other than root since ssh using root account is not recommended you need to add this extra option 

--extra-vars='ansible_become_pass=youruserpassword'

The playbook only packages an OpenSRP WAR file if it doesn't exist in your deployment machine's WAR directory (default is /tmp/opensrp-wars). You will need to delete the WAR file from this directory if you want the playbooks to repackage the project.

The option --skip-tag nginx  is used to skip setting up nginx with ssl encryption since we are doing this locally but for production you can omit it so that the nginx web server is installed and setup as well.

The option -vvvv  is for verbosity. It logs into the terminal the ansible processes. 

Other options that you can add while deploying to a particular environment can be:

Option

Description

Option

Description

-e "certbot_create_certs=true"

Force the playbook to generate a new LetsEncrypt certificate and key. Only applies for sites that have been set to use LetsEncrypt certs.

 

For production or version controlled setups kindly use vault to store the credentials.

vault.yml - Has encrypted sensitive information/secrets used in the vars.yml file. For the sample inventory the passwords and secrets are dummy for real implementation you would require serious passwords/keys.

NOTE: the content of vault.yml is encrypted to protect the sensitive information about the infrastructure implementation and you will need vault password to decrypt it first to make that content usable. 

For the purpose of demo a dummy password is used to encrypt the contents of vault.yml to protect the secrets and keys used for deployment. Again when working with real implementation ensure you use strong passwords.

To decrypt the contents of the vault.yml file first we will create a file to hold the dummy password by running the following commands. 

1 2 $ touch ~/.vaultpass $ echo dummy_vault_password > ~/.vaultpass

Basically what the commands do is create a file inside home directory, then appends the dummy_vault_ password to the file.

You can edit the contents of your vault file in the terminal by running the following command. This will display the content now in plain text format.

1 $ ansible-vault edit --vault-password=~/.vaultpass


If you are not familiar with vim editor then just decrypt the contents of the vault file and open the file in your favorite GUI editor like visual studio code, gedit, sublimetext, atom, etc. You will see the content in plain text format and you can modify them as you wish.

1 $ ansible-vault decrypt --vault-password=~/.vaultpass

To encrypt simply replace decrypt  with encrypt and provide new password. This would be necessary to avoid exposing sensitive secrets on a public repository.