This Guid will help you to learn Ansible basics and some practical stuff.

What is Ansible ?

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems

In Summery:

Why Ansible ?

Where we need to Ansible ?

Terminology

  1. Playbook variable : which we defined in Playbook or while running playbook, it’s globally use everywhere in playbook and it’s also override the other varible which has same name.
# Following way to define variable in playbook
vars:
  test: 'abc'

# Inside tasks ( Runtime variable )
- set_fact: test="abc"

Or we can specify while running command, ( Runtime variable )

ansible-playbook -e test=abc playbook.yaml
  1. Defualt variable : When we run playbook, it’s try to search variable in some default location which not found in playbook book variable.

  2. group_vars/hostname : this is hostbased variable, so first ansible will try to search in hostbased variable, let say ansible is trying to configure host1 then it will look for group_vars/host1 file for variable

  3. group_vars/groupname : this is groupbased variable, if variable not found in hostbased variable then it will try search in groupbased.

  4. group_vars/all : at the last it’s try to search in “all” which is plain YAML variable file

  5. vars_file: or you can include your custom variable file.

Inventory:

There are two types of inventory in ansible

1) Static Inventory: plain text file where your all hosts defined with groups Example:

# Hosts it's comments
192.168.0.2  ansible_ssh_user=root ansible_ssh_pass=redhat var1=test
192.168.0.3  ansible_ssh_user=root ansible_ssh_pass=redhat var1=test
192.168.0.10  ansible_ssh_user=root ansible_ssh_pass=redhat name=blabla


# Groups it's comments
[webservers]
192.168.0.1
192.168.0.3

[dbservers]
192.168.0.10

To check hosts:

ansible -i inv_file all --list-host

it will return all ips from inventory

ansible -i inv_file webservers --list-host

it will return all ips from webservers groups

To run uptime command on all hosts ( this is add-hoc command )

ansible -i inv_file all -a 'uptime'

2) Dynamic Invenotory: it’s script which will return the hosts/groups details from any host providers like AWS, Docker, Rackspace etc.

Lets do some practical stuff

Goal

We will install ansible on your local machine and setup following things in remote machine

Install Ansible on local machine

sudo apt-add-repository -y ppa:ansible/ansible
sudo apt-get update
sudo apt-get install -y ansible

Create Playbook

We will create one common role, which will do following things

  1. os_hardening : All things related to OS hardening
  2. base_package : Install or compile required packages

Also there will be one single file to manage global variables, like in future if we need to change version of any application or links etc.

Now create one dir and cd into it then create yml files

mkdir deploy-nodes && cd deploy-nodes

Create playbook structure

mkdir -p roles/common/tasks
touch site.yml
touch roles/common/tasks/main.yml
touch roles/common/tasks/os_hardening.yml
touch roles/common/tasks/base_packages.yml
touch group_vars/all

So our final structure as below :

|-- ansible_hosts
|-- group_vars
|  '-- all
|-- roles
| '-- common
|  '-- tasks
|    |-- base_packages.yml
|    |-- main.yml
|    '-- os_hardening.yml
'-- site.yml

Now let’s configure the os_hardening.yml

There are many things you can do to secure your OS but for learning ansible, we will do basic things, like disable root user in ssh and adding MaxAuthTries 3

Let’s first defined ssh related variables in vars.yml file

Edit “group_vars/all” and configure as below :

---
sshd_config: '/etc/ssh/sshd_config'

Note: file started with “---”, because it YML file, so every YML file, should have this entry.

Configure the “roles/common/tasks/os_hardening.yml

---
  - name: SSHD# Disable Root login
    lineinfile:
        backup=yes
        state=present
        dest={{ sshd_config }}
        regexp='^PermitRootLogin'
        line='PermitRootLogin no'

  - name: SSHD# Updating MaxAuthTries to 3
    lineinfile:
        backup=yes
        state=present
        dest={{ sshd_config }}
        regexp='^MaxAuthTries'
        line='MaxAuthTries 3'

  - name: SSHD# Restarting ssh service
    service:
      name=ssh
      state=restarted

Explanation :

  1. First it will take backup destination file then search line starting with “PermitRootLogin” and replace with “PermitRootLogin no”
  2. Again search and replace but if search not found then it will add “MaxAuthTries 3”
  3. Finally it will restart ssh to affect the changes. Configure “roles/common/tasks/base_package.yml”
---
  - name: Install list of packages
    action:
       apt
       update_cache=yes
       cache_valid_time=600
       pkg={{item}}
       state=installed
    with_items:
    - unzip
    - build-essential
    - openssl
    sudo: true
    when:
       ansible_distribution == 'Debian' or
       ansible_distribution == 'Ubuntu'

Explanation :

It will first do apt-get update if it is not run last 10 min ( cache_valid_time=600 ), then it will install mention packages.

Configure “roles/common/tasks/main.yml” file

---
 - include: os_hardening.yml
 - include: base_packages.yml

Configure “site.yml” file

---
  - hosts: all
    sudo: true
    roles:
       - common

Add your hosts to ansible_hosts file

[servers]
remote-ip-address ansible_ssh_user=remote-user ansible_sudo_pass=password ansible_ssh_pass=password

Note: if there is any special character in your password then you need to escape it Ex. if password is: p@ssw1rd then use: p\@ssw1rd

Now let’s run the ansible command to setup remote host

ansible-playbook -vvv -i ansible_hosts site.yml

If you face “ssh fingerprint” issue then do following thing and run above command again:

sudo sed -i.bkp 's/^#host_key_checking = False/host_key_checking = False/' /etc/ansible/ansible.cfg

You can find this playbook on github, check this page