Back to Blog
Automation

Ansible 101 - a newbie guide to Ansible - part 1/2

March 3, 2025
10 min read
Share:

Ansible 101 - a newbie guide to Ansible - part 1/2


Table of Contents

What is Ansible?

Use cases

SSH Authentiction with keys

Ansible Setup

Ansible Inventory

Ansible playbooks



What is Ansible?

Ansible is an open source CLI automation software developped by Michael DeHaan (the author of the provisioning server application Cobbler and co-author of the Fedora Unified Network Controller (Func) framework for remote administration.) Michael created Func and Ansible trying to solve the issue as shown below

What's the problem


Ansible is one of most popular DevOps tools created with Python to help in the orchestration, automation, configuration, and management of IT infrastructure. StackShare lists more than 1,000 companies that use Ansible, including Intel, Evernote, and Hootsuite, NASA, AkumenIA and more. Ansible has Ansible Galaxy, an online community for finding, sharing and re-using Ansible automation content.

There are tools such as Ansible in the market like Chef and Puppet. But when it comes to ease of setup and installation, Ansible dominates the other two, as it has an 'agentless' architecture, Unlike Chef and Puppet which follow master-agent or master-slave architecture.


Ansible Use cases

Ansible can be used in many scenarios like configuring systems, deploying software, and orchestrating advanced workflows to support application deployment, system updates, and more. Ansible's main strengths are simplicity and ease of use that's why you can almost adapt it for many automation scenarios.


SSH Authentiction with keys

Unlike many other tools Ansible doesn't need anything to be installed on target machine, all it needs is SSH connection from the control machine to the target machine and it will do its magic. When talking about SSH, it's essential to clarify some ideas, SSH which stands for Secure SHell, came as a better alternative to authenticate to SFTP servers, instead of username password method. A funny information is that the Elon Muscles (popular) password in 2017 was "123456" lol. According to a study done by Beyond Identity Gen Zers ranked as the worst in having a password for the longest time, as 40% said their oldest password was between 6-10 years old. The older generations’ percentages in that category were much lower, with Boomers at 13.7%, Gen X at 18%, and Millennials at 22.3%. And with machines getting more powerful it will became a matter of time to brute force passwords in short times. Using SSH key authentication method can be a bit more complex, but it increases security when loggin to SFTP servers. The way SSH keys work is

(1) you generate a pair of keys (public and private) which cryptographic keys on the control machine / SSH client

(2) the public key should be stored on the target machine

(3) when trying to log into the target machine, the target checks for public key existence, and it generates a random encrypted string with that key, this latest can only be decrypted with the associated privated key.

(4) Upon receiving the encrypted message from the target, the SSH client will try to decrypt that message using the private key and send it back to the target, if it matches up server negotiates parameters and open a secure chanel for the client to log in to the server.


Ansible Setup

The control machine can be a linux machine, and if it is Windows you can install WSL to proceed, you can install Ansible either by:

(1) a package manager (apt, yum, brew...)

sudo apt install ansible -y

or with:

(2) python using pip (btw did you know know that pip is an abbreviation for preferred installer program)

python3 -m pip install --user ansible

after installing Ansible, we need to setup SSH in the target machine. By running the following commands:

sudo apt install openssh-server
sudo ufw allow ssh
systemctl status ssh

you will install an SSH server, enable application profile on UFW firewall (UFW is a cool program, I will write a blog on it in the near future), then check ssh state (which should be active).

Also, let's create a user named Ansible with its password on the target machine using the following

useradd -m -s /bin/bash ansible
passwd ansible

generate public and private key on the control machine

ssh-keygen

this command will prompts you to enter some information, among them is the /path/to/key

then copy the public key to the target using

ssh-copy-id -i /path/to/key ansible@target-machine

on the target machine, add ansible user to sudoers group as it will need elivated privileges to install software and run superuser commands

sudo su
echo -e 'ansible\tALL=(ALL:ALL)\tNOPASSWD:\tALL' > /etc/sudoers.d/ansible

the e flag of echo command is to enable interpreting backslash escapes.

All set now, you can check SSH authentication validity with

ssh -i /path/to/key ansible@host

HOORAY ansible is set up.

Ansible inventory

We need to test if everything works as expected, in order to do that we need to run some command on the target machine, we do this by informing ansible with target machines information, and such information are stored in what is called an inventory file, by default if you didn't add a custom inventory, Ansible will use a default inventory stored in /etc/ansible/hosts, an inventory syntax looks like the following

SERVER_NAME ansible_host=IP ansible_private_key_file=FILE_PATH ansible_ssh_user=USER
__same_as_line_above__ ansible_ssh_port=PORT

in inventory you specify information such as ansible_host which should be either a dns name or ip address, ansible_private_key_file which points to the path of the private key to authenticate the user with against the target, some parameters have default values such as ansible_ssh_port which is by default 22. Declared variable in each line are meant to be assigned to the host of that line

Now we can test ansible connection with the ping module:

ansible -i inventory name_for_server -m ping should return SUCCESS pong response, it's like a 200-OK-meme

In order to not specify each time the inventory to use with the i flag, we can create ansible.cfg file which points to default inventory to use:

[defaults]

INVENTORY = ./inventory

Now we can ping with:

ansible -m ping

which will run ping againt all hosts specified in the inventory.

Other parameters that you can use in the inventory file are:

  • ansible_connection: by default ansible will try to use SSH, use this flag to indicate other connection methods such as winrm.
  • ansible_port: the port to which the connection establishes, by default 22
  • ansible_user: the default ssh user name to use.
  • ansible_ssh_pass: User password, for security reasons try to use tools such as hashicorp vault.

Sometimes you need to run the same commands on a group of servers, and run other commands on other servers, maybe database servers and web servers. what you can do is creating groups of servers as below:

[webservers]
server1 ansible_host=23.0.2.9
server2 ansible_host=23.0.2.10

[dbservers]
server3 ansible_host=23.0.2.11
server4 ansible_host=23.0.2.12

if some groups share some variables values you can pass them to those groups as follows:

[webservers]
webserver1 ansible_host=23.0.2.9
webserver2 ansible_host=23.0.2.10

[dbservers]
dbserver1 ansible_host=23.0.2.11
dbserver2 ansible_host=23.0.2.12

[webservers:vars]
ansible_user=user1

[dbservers:vars]
ansible_user=user2

when running an adhoc (a command which can be run individually to perform quick functions) or a module (we will see this in the next blog), you can target one host, a group of hosts or all machines in the inventory, this is done using patterns:

ansible PATTERN -m MODULE_NAME -a "MODULE_OPTIONS"

example to only target dbservers group:

ansible dbservers -m service -a "name=mysqld enabled=yes state=started"

let's imagine a scenario where we have prod and development servers, and we need to run specific commands on development but not on prod, we can adjust our inventory to indicate this with:

[webservers]
webserver1 ansible_host=23.0.2.9
webserver2 ansible_host=23.0.2.10

[dbservers]
dbserver1 ansible_host=23.0.2.11
dbserver2 ansible_host=23.0.2.12

[development]
webserver1
dbserver1

[production]
webserver2
dbserver2

so now using the pattern below the command will be applied on the dev servers:

ansible dbservers:\&development -m ping

or:

ansible dbservers:\!production -m ping

here's a table about the different patterns:

patternresult
allall hosts in the inventory
host1a single host (host1)
host1:host2host1 and host2
group1only group1
group1:group2hosts of group1 and group2
group1:\&group2servers that are both in group1 and group2
group1:\!group2servers in group1 with those in group2 excluded



Ansible Playbook

In Ansible, Playbooks are config files written in yaml syntax, they are the orchestration language of Ansible, it's in them we define what we want the tool to do aka plays, and a play is a set of taks/activities.

The executions of playbooks can either run synchronously or asynchronously, to elaborate, the plays run in order from top to bottom, and when different plays should be running on different hosts, ansible will orchestrate multi-machine deployments.

A simple play will define at least two things:

  • The target hosts (using a pattern)
  • Tasks to execute

Here's a simple playbook.yaml to update PostgreSQL servers

YAML
- name: Update pgsql servers hosts: dbservers remote_user: root tasks: - name: psql shouls be at the latest version ansible.builtin.yum: name: postgresql state: latest - name: postgresql should be started ansible.builtin.service: name: postgresql state: started

remote_user is the user account the SSH connection. to run the above playbook we will use the ansible-playbook command as follow:

BASH
ansible-playbook playbook.yml

ansible-playbook accepts some flags such as --forks which specify number of parallel processes to use by default it's 5, and --verbose which gives you more detailed information about tasks execution.

Before running playbooks it is always good to lint your files to avoid bugs white the execution, you can achieve such thing using the ansible-lint CLI command:

ansible-lint playbook.yml

ansible.builtin.service and ansible.builtin.yum we used the playbook are called Modules, which are pieces of code that can apply changes to the system, run commands, edit files, manage databases, provision cloud, and more…

you can check available modules by visiting Ansible "All Modules" page, our check them out using ansible-doc CLI command as follow:

ansible-doc –list

to learn more about a specific module, use:

ansible-doc module_name

which will give you a detailed description about the module, along with examples on how to use it.



Until here this blog ends, we will see in the next one: more on modules, variables, jina2 template, tasks delegation, some advanced topics, and more...

Enjoyed this article? Share it!