There is a new version of this tutorial available for Ubuntu 22.04 (Jammy Jellyfish).

How to Install and Configure Ansible on Ubuntu 20.04

Ansible is a very popular configuration management tool designed to streamline the process of controlling a large number of servers. You can control as many servers and run processes on them simultaneously from a single node.

Ansible doesn't require any special software required to be installed on the server nodes and can control them over SSH.

In this guide, we will learn how to install and configure Ansible on an Ubuntu 20.04 server.


  • Two or more Ubuntu 20.04 based server systems with OpenSSH server installed.
  • Both the server and nodes are accessible via public IP addresses.
  • A non-root user with sudo privileges set up on the Ansible server and a root user with a password set up on the Ansible clients.

Install Ansible

Ansible's official repository doesn't support Ubuntu 20.04 due to a bug in Ubuntu's python library at the time of writing this tutorial.

Fortunately, Ubuntu ships with Ansible 2.9 which is what we will install. Run the following command to install Ansible.

$ sudo apt install ansible -y

Test your installation by running the following command.

$ ansible --version
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/username/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0]

Setting up Inventory File

To be able to connect to multiple hosts, you need a file that will record the details of the nodes. This file is called the Inventory file.

Depending on how many servers you want to control, Ansible's Inventory file also allows you to arrange them in groups and subgroups. You can also set custom variables applicable to select hosts or groups which can be further used while passing on the instructions.

Ansible ships with a default Inventory file available at /etc/ansible/hosts. Open it with the Nano editor.

$ sudo nano /etc/ansible/hosts

Paste the following code at the bottom of the file.

server1 ansible_host=
server2 ansible_host=
server3 ansible_host=


The servers section defines the list of nodes you want to connect to. You can create as many groups to arrange servers in multiple groups.

The all:vars group sets the ansible_python_interpreter parameter on all the hosts in the inventory. It makes sure that Ansible uses Python 3 executable instead of Python 2 which has been removed from recent Ubuntu versions.

When you’re finished, save and close the file by pressing CTRL+X then Y and ENTER to confirm your changes.

Note: You can also create your own Inventory file in any location of your choice which you can then pass off by using -i parameter while running Ansible commands.

You can check your inventory list by the following command.

$ ansible-inventory --list -y
          ansible_python_interpreter: /usr/bin/python3
          ansible_python_interpreter: /usr/bin/python3
          ansible_python_interpreter: /usr/bin/python3
    ungrouped: {}

Organizing Servers into Groups and Subgroups

This is a useful tip if you have a lot of servers with some servers performing specific functions. For example, you can use this method to group web servers and database servers separately. You can even make a host part of multiple groups. You can even make a host part of multiple groups. To achieve that, your inventory file should look something like the following.





Set up SSH Keys

For Ansible to be able to connect to the servers, you must configure SSH keys between your Ansible server and hosts specified in the inventory file. This will work only if the Ansible clients don't have a public key enabled and have a root account enabled with a password.

Use the following steps to create and set up an SSH key for Ansible and its nodes.

Create the key for Ansible.

$ ssh-keygen -t rsa -b 4096 -C "Ansible key"

Copy the public key to your accounts on the remote servers. For this, we will use the ssh-copy-id command.

$ ssh-copy-id -i $HOME/.ssh/ [email protected]
$ ssh-copy-id -i $HOME/.ssh/ [email protected]
$ ssh-copy-id -i $HOME/.ssh/ [email protected]

That's all. Now Ansible should be able to talk to your servers.

Setup SSH Keys on Nodes with existing Public Key

If the clients already have public keys enabled, then you will have to follow certain extra steps. For that, you need to create a new user-accessible only by Ansible on every node server. That user will have sudo privileges accessible without a password and can be accessed only from your ansible server.

To create a ansible user, run the following command.

$ sudo adduser ansible

Choose a strong password and leave all the other fields empty.

Now, configure password-less sudo access to this user through the following command.

$ echo "ansible ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ansible

Now, that you have the new user added and configured, you can copy the SSH key from your ansible server to the node server using the following command.

$ ssh-copy-id [email protected]

You will be prompted a password for the ansible user. Enter it and the SSH key will be copied.

Next, disable the password-based login for the ansible user on the node server.

$ sudo usermod -L ansible

Now, your node server is only accessible from the Ansible server since only that server has the public key for it and you can't use it with sudo privileges on the node server directly since password login is disabled.

You will have to repeat these steps for each node server. Also, replace the root user with the ansible user in this tutorial.

Test Connection

After setting up the inventory file and SSH keys, we should check if Ansible is able to connect to the servers.

Type the following command to check the connection. This command will test the connection to all the servers from the inventory file.

$ ansible all -m ping -u root

This command uses Ansible's ping module to run a connectivity test on all the servers. You should get an output like the following.

server1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
server2 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
server3 | SUCCESS => {
    "changed": false, 
    "ping": "pong"

If this is the first time you are using Ansible, you will be asked to confirm the authenticity of all the servers. When prompted, type yes and press ENTER to confirm.

Run Some basic commands

Let us run some basic commands on the servers using Ansible. To run any command on the server, the following format is used.

$ ansible all -a "command" -u <username>

Check Disk Usage

First, let us check disk usage on all our servers.

$ ansible all -a "df -h" -u root
server1 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
udev            3.9G     0  3.9G   0% /dev
tmpfs           798M  624K  798M   1% /run
/dev/vda1       155G  2.3G  153G   2% /
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/vda15      105M  3.6M  101M   4% /boot/efi
tmpfs           798M     0  798M   0% /run/user/0

server2 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G     0  2.0G   0% /dev
tmpfs           395M  608K  394M   1% /run
/dev/vda1        78G  2.2G   76G   3% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/vda15      105M  3.6M  101M   4% /boot/efi
tmpfs           395M     0  395M   0% /run/user/0

Target Individual Hosts and Groups

Until now, we were running commands on all remote servers at once. But that is not always the case. To run a command on just one server, you should use the following format.

$ ansible server1 -a "uptime" -u root
server1 | CHANGED | rc=0 >>
 21:38:26 up 11 min,  2 users,  load average: 0.00, 0.20, 0.19

The above command checks the uptime on server1 from the inventory group.

You can also target multiple servers using the following format.

$ ansible server1:server2 -m ping -u root

You can also target groups or subgroups from the inventory file directly.

$ ansible groupname -m ping -u <username>

Update all servers

For this tutorial, we are assuming all the remote servers are running Debian or Ubuntu OS.

Run the following command to update the software on all your servers.

$ ansible all -m apt -a "update_cache=yes upgrade=yes" -u root

-m parameter defines the module for Ansible to run. -a refers to the arguments or commands for the associated module. Here, we are using the apt module of Ansible to update servers just like we used the ping module in our last example. update_cache updates the APT cache on the server and upgrade=yes tells Ansible to run apt upgrade command.

To update your CentOS servers, you can use the same command by replacing apt with yum and for Fedora servers, you can replace apt by dnf.

If you are using the ansible user as documented above, you need to modify the ansible command to run with elevated sudo privileges.

$ ansible server2 -m apt -a "update_cache=yes upgrade=yes" -K -b -u ansible

Here, -K asks for privilege escalation password. -b runs the ansible operation with become which allows you to be another user. Both variables combined allow ansible to run with elevated sudo privileges. You will need to use this for all commands which require sudo privileges.

Sometimes, some of these update commands may require a reboot so run the following command to reboot all your servers.

$ ansible all -a "reboot" -u root

These were just some of the basic commands you can run using Ansible.


That wraps up our tutorial on installing and configuring Ansible on Ubuntu 20.04 based server. If you have any questions, post them in the comments below.

Share this page:

1 Comment(s)