How to Install Ansible on Ubuntu 20.04 LTS (Focal Fossa)


In this article, I will take you through the steps to install ansible on Ubuntu 20.04 LTS. Ansible is a free and simple IT automation tool that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other such needs. It is designed for multi-tier deployments to play a central role in managing number of hosts(including cloud platform and on-premise hosts) from a central location without putting much effort. It is powerful agentless tool that works almost everywhere and with everything.  Here we will see how to install Ansible on Ubuntu 20.04 LTS control node and manage hosts from there.


Lab Setup

In our lab, we are going to use two node setup in which one is the Ubuntu 20.04 LTS based control node and another is Linux Mint 21 based ansible host with IP address as shown below.

Control host - 20.04 LTS)
Ansible host - Mint )


How to Install Ansible on Ubuntu 20.04 LTS (Focal Fossa)

How to Install Ansible on Ubuntu 20.04 LTS (Focal Fossa)

Also Read: How to Install Ansible on Ubuntu 18.04 with Best Practices

Step 1: Prerequisites

a) You should have a running Ubuntu 20.04 LTS control server.

b) You should have a running Linux Mint 21 ansible host.

b) You should have sudo or root access to run privileged commands.

c) You should have apt or apt-get utility available in your Server.


Step 2: Update Your Server

Before going through the steps to install ansible on the server, it is recommended to first update and sync all the installed packages with the latest available versions from default Ubuntu repo using sudo apt update && sudo apt upgrade command as shown below.

cyberithub@ubuntu:~$ sudo apt update && sudo apt upgrade
[sudo] password for cyberithub:
Hit:1 public InRelease
Hit:2 stable InRelease
Hit:3 focal InRelease
Get:4 focal-security InRelease [114 kB]
Get:5 focal-updates InRelease [114 kB]
Get:6 focal-security/main amd64 Packages [1,896 kB]
Get:7 focal-backports InRelease [108 kB]
Get:8 focal-updates/main i386 Packages [762 kB]
Get:9 focal-updates/main amd64 Packages [2,269 kB]
Get:10 focal-security/main i386 Packages [530 kB]
Get:11 focal-security/main Translation-en [311 kB]
Get:12 focal-security/main amd64 DEP-11 Metadata [40.8 kB]


Step 3: Install software-properties-common

Before adding the ansible repository, check the installation of software-properties-common package by running sudo apt install software-properties-common command as shown below. If it's not installed then it will install, otherwise it will just display you below output.

cyberithub@ubuntu:~$ sudo apt install software-properties-common
[sudo] password for cyberithub:
Reading package lists... Done
Building dependency tree
Reading state information... Done
software-properties-common is already the newest version (
software-properties-common set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 31 not upgraded.


Step 4: Add Repository

Then add the ansible PPA repository using sudo add-apt-repository --yes --update ppa:ansible/ansible to download all the ansible tools.

cyberithub@ubuntu:~$ sudo add-apt-repository --yes --update ppa:ansible/ansible
Hit:1 public InRelease
Get:2 focal-security InRelease [114 kB]
Get:3 focal-security/main i386 Packages [530 kB]
Get:4 focal-security/main amd64 Packages [1,895 kB]
Get:5 focal-security/main amd64 DEP-11 Metadata [40.7 kB]
Get:6 focal-security/main amd64 c-n-f Metadata [11.5 kB]
Get:7 focal-security/universe i386 Packages [574 kB]
Get:8 focal-security/universe amd64 Packages [778 kB]
Get:9 focal-security/universe amd64 DEP-11 Metadata [94.1 kB]
Get:10 focal-security/universe amd64 c-n-f Metadata [16.8 kB]
Get:11 focal-security/multiverse amd64 DEP-11 Metadata [940 B]
Get:12 stable InRelease [1,811 B]
Hit:13 focal InRelease
Get:14 focal InRelease [18.0 kB]
Get:15 stable/main amd64 Packages [1,092 B]
Get:16 focal-updates InRelease [114 kB]
Get:17 focal/main i386 Packages [1,132 B]
Get:18 focal-backports InRelease [108 kB]
Get:19 focal/main amd64 Packages [1,132 B]
Get:20 focal-updates/main amd64 Packages [2,270 kB]
Get:21 focal/main Translation-en [756 B]
Get:22 focal-updates/main i386 Packages [763 kB]
Get:23 focal-updates/main Translation-en [395 kB]
Get:24 focal-updates/main amd64 DEP-11 Metadata [275 kB]
Get:25 focal-updates/main amd64 c-n-f Metadata [16.1 kB]
Get:26 focal-updates/universe amd64 Packages [1,009 kB]
Get:27 focal-updates/universe i386 Packages [705 kB]
Get:28 focal-updates/universe Translation-en [234 kB]
Get:29 focal-updates/universe amd64 DEP-11 Metadata [407 kB]
Get:30 focal-updates/universe amd64 c-n-f Metadata [23.2 kB]
Get:31 focal-updates/multiverse amd64 DEP-11 Metadata [940 B]
Get:32 focal-backports/main amd64 DEP-11 Metadata [7,984 B]
Get:33 focal-backports/universe amd64 DEP-11 Metadata [30.5 kB]
Fetched 10.4 MB in 8s (1,230 kB/s)
Reading package lists... Done


Step 5: Install Ansible

Now you can install all the ansible tools from the added PPA repository by using sudo apt install ansible -y command as shown below. This will download all the packages along with all its dependencies.

cyberithub@ubuntu:~$ sudo apt install ansible -y
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
ansible-core python3-jinja2 python3-jmespath python3-kerberos python3-ntlm-auth python3-packaging python3-pyparsing python3-requests-kerberos
python3-requests-ntlm python3-resolvelib python3-winrm python3-xmltodict sshpass
Suggested packages:
python-jinja2-doc python-pyparsing-doc
The following NEW packages will be installed:
ansible ansible-core python3-jinja2 python3-jmespath python3-kerberos python3-ntlm-auth python3-packaging python3-pyparsing python3-requests-kerberos
python3-requests-ntlm python3-resolvelib python3-winrm python3-xmltodict sshpass
0 upgraded, 14 newly installed, 0 to remove and 39 not upgraded.
Need to get 22.3 MB of archives.
After this operation, 323 MB of additional disk space will be used.
Get:1 focal/main amd64 python3-resolvelib all 0.5.4-2ppa~focal [12.6 kB]
Get:2 focal/main amd64 python3-jinja2 all 2.10.1-2 [95.5 kB]
Get:3 focal/main amd64 ansible-core all 2.12.10-1ppa~focal [943 kB]
Get:4 focal/main amd64 python3-pyparsing all 2.4.6-1 [61.3 kB]
Get:5 focal/main amd64 python3-packaging all 20.3-1 [26.8 kB]
Get:6 focal-updates/main amd64 python3-jmespath all 0.9.4-2ubuntu1 [21.5 kB]
Get:7 focal/universe amd64 python3-kerberos amd64 1.1.14-3.1build1 [22.6 kB]
Get:8 focal/universe amd64 python3-ntlm-auth all 1.1.0-1 [19.6 kB]
Get:9 focal/universe amd64 python3-requests-kerberos all 0.12.0-2 [11.9 kB]
Get:10 focal/universe amd64 python3-requests-ntlm all 1.1.0-1 [6,004 B]
Get:11 focal/universe amd64 python3-xmltodict all 0.12.0-1 [12.6 kB]
Get:12 focal/universe amd64 python3-winrm all 0.3.0-2 [21.7 kB]
Get:13 focal/universe amd64 sshpass amd64 1.06-1 [10.5 kB]
Get:14 focal/main amd64 ansible all 5.10.0-1ppa~focal [21.0 MB]
Fetched 22.3 MB in 18s (1,247 kB/s)
Selecting previously unselected package python3-jinja2.
(Reading database ... 207245 files and directories currently installed.)
Preparing to unpack .../00-python3-jinja2_2.10.1-2_all.deb ...
Unpacking python3-jinja2 (2.10.1-2) ...
Selecting previously unselected package python3-pyparsing.
Preparing to unpack .../01-python3-pyparsing_2.4.6-1_all.deb ...
Unpacking python3-pyparsing (2.4.6-1) ...
Selecting previously unselected package python3-packaging.
Preparing to unpack .../02-python3-packaging_20.3-1_all.deb ...
Unpacking python3-packaging (20.3-1) ...
Selecting previously unselected package python3-resolvelib.
Preparing to unpack .../03-python3-resolvelib_0.5.4-2ppa~focal_all.deb ...
Unpacking python3-resolvelib (0.5.4-2ppa~focal) ...
Selecting previously unselected package ansible-core.
Preparing to unpack .../04-ansible-core_2.12.10-1ppa~focal_all.deb ...
Unpacking ansible-core (2.12.10-1ppa~focal) ...
Selecting previously unselected package ansible.
Preparing to unpack .../05-ansible_5.10.0-1ppa~focal_all.deb ...
Unpacking ansible (5.10.0-1ppa~focal) ...
Selecting previously unselected package python3-jmespath.
Preparing to unpack .../06-python3-jmespath_0.9.4-2ubuntu1_all.deb ...
Unpacking python3-jmespath (0.9.4-2ubuntu1) ...
Selecting previously unselected package python3-kerberos.
Preparing to unpack .../07-python3-kerberos_1.1.14-3.1build1_amd64.deb ...
Unpacking python3-kerberos (1.1.14-3.1build1) ...
Selecting previously unselected package python3-ntlm-auth.
Preparing to unpack .../08-python3-ntlm-auth_1.1.0-1_all.deb ...
Unpacking python3-ntlm-auth (1.1.0-1) ...
Selecting previously unselected package python3-requests-kerberos.
Preparing to unpack .../09-python3-requests-kerberos_0.12.0-2_all.deb ...
Unpacking python3-requests-kerberos (0.12.0-2) ...
Selecting previously unselected package python3-requests-ntlm.
Preparing to unpack .../10-python3-requests-ntlm_1.1.0-1_all.deb ...
Unpacking python3-requests-ntlm (1.1.0-1) ...
Selecting previously unselected package python3-xmltodict.
Preparing to unpack .../11-python3-xmltodict_0.12.0-1_all.deb ...
Unpacking python3-xmltodict (0.12.0-1) ...
Selecting previously unselected package python3-winrm.
Preparing to unpack .../12-python3-winrm_0.3.0-2_all.deb ...
Unpacking python3-winrm (0.3.0-2) ...
Selecting previously unselected package sshpass.
Preparing to unpack .../13-sshpass_1.06-1_amd64.deb ...
Unpacking sshpass (1.06-1) ...
Setting up python3-ntlm-auth (1.1.0-1) ...
Setting up python3-resolvelib (0.5.4-2ppa~focal) ...
Setting up python3-kerberos (1.1.14-3.1build1) ...
Setting up sshpass (1.06-1) ...
Setting up python3-xmltodict (0.12.0-1) ...
Setting up python3-jinja2 (2.10.1-2) ...
Setting up python3-pyparsing (2.4.6-1) ...
Setting up python3-jmespath (0.9.4-2ubuntu1) ...
Setting up python3-requests-kerberos (0.12.0-2) ...
Setting up python3-requests-ntlm (1.1.0-1) ...
Setting up python3-packaging (20.3-1) ...
Setting up python3-winrm (0.3.0-2) ...
Setting up ansible-core (2.12.10-1ppa~focal) ...
Setting up ansible (5.10.0-1ppa~focal) ...
Processing triggers for man-db (2.9.1-1) ...


Step 6: Create SSH Key Pair

Now that your control node is setup, it is time to setup ansible host. For that you need to first create a ssh key pair for secure host connection from control node. To create a new key pair, run ssh-keygen command and provide a strong passphrase to protect your private key from being used by anonymous users.

cyberithub@ubuntu:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cyberithub/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/cyberithub/.ssh/id_rsa
Your public key has been saved in /home/cyberithub/.ssh/
The key fingerprint is:
SHA256:RAh9vLxhJ/9HlPRmOV9PdWq0fRj9nkjfOm9RL6anOwM cyberithub@ubuntu
The key's randomart image is:
+---[RSA 3072]----+
|    .o o. .      |
|      o.o + +    |
|       o.. o O=  |
|       .* . .Bo@ |
|       .S* .oo=@ |
|        . E .++* |
|          o + o. |
|           = = . |
|           oB +. |


Step 7: Configure Ansible host

Once you have the public and private key generated, you need to copy the public key to your ansible host using ssh-copy-id utility. To copy the public key, you need to use ssh-copy-id <user_name>@<host> syntax. In our case we are going to copy public key to host using user cyberithub . So for that we just need to run ssh-copy-id cyberithub@ command as shown below.

cyberithub@ubuntu:~$ ssh-copy-id cyberithub@
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/cyberithub/.ssh/"
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:4+zOaodwkzfImdbDWGStUB6nwmpyOcdEPg1Ts8TR3Eg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
cyberithub@'s password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'cyberithub@'"
and check to make sure that only the key(s) you wanted were added.


Step 8: Setup Inventory 

In the next step, you need to setup the inventory file to manage your hosts. By default, you will find the inventory file in /etc/ansible/hosts but you can also use a custom path using -i option. Ideally you can add as much hosts as you need in the inventory file but in our case since we have only one host so we are going to add that one only at the end of the file as shown below.

cyberithub@ubuntu:~$ sudo nano /etc/ansible/hosts
[sudo] password for cyberithub:

# This is the default ansible 'hosts' file.
# It should live in /etc/ansible/hosts
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups

# Ex 1: Ungrouped hosts, specify before any group headers:


# Ex 2: A collection of hosts belonging to the 'webservers' group:

## [webservers]

# If you have multiple hosts following a pattern, you can specify
# them like this:

## www[001:006]

# Ex 3: A collection of database servers in the 'dbservers' group:

## [dbservers]

# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]

server1 ansible_host=

After setting up the inventory file, you can check the list of inventory by using ansible-inventory --list -y command as shown below.

cyberithub@ubuntu:~$ ansible-inventory --list -y
    ungrouped: {}


Step 9: Testing Connection

After setting up the host, it is time to test the connection by pinging all the hosts in the inventory file using ansible all -m ping command as shown below.  If you see pong as the ping response on the output then this confirms the successful setup of ansible hosts.

cyberithub@ubuntu:~$ ansible all -m ping
Enter passphrase for key '/home/cyberithub/.ssh/id_rsa':
[WARNING]: Platform linux on host server1 is using the discovered Python interpreter at /usr/bin/python3.10, but future installation of another Python
interpreter could change the meaning of that path. See for more
server1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.10"
    "changed": false,
    "ping": "pong"


Step 10: Using Ansible Playbook

Now that ansible setup is completed, it is time to write an example playbook. In the below example, we are creating operator.yml playbook where we are using a simple arithmetic operation of raising left operand to the power of right operand by using two variables a and b. Then displaying the result on the output using debug module as shown below.

cyberithub@ubuntu:~$ nano operator.yml
 - name: Arithmetic Operator
   hosts: localhost
   gather_facts: false
     a: 2
     b: 3
    - name: "Raise left operand to the power of right operand"
         - "Raise left operand to the power of right operand : {{ a**b }}"


cyberithub@ubuntu:~$ ansible-playbook operator.yml

PLAY [Arithmetic Operator] **********************************************************************************************************************************

TASK [Raise left operand to the power of right operand] *****************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Raise left operand to the power of right operand : 8"

PLAY RECAP **************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Leave a Comment