How to Install and Configure Ansible on Ubuntu 20.04
This tutorial exists for these OS versions
- Ubuntu 22.04 (Jammy Jellyfish)
- Ubuntu 20.04 (Focal Fossa)
- Ubuntu 18.04 (Bionic Beaver)
On this page
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.
Prerequisites
- 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.
[servers]
server1 ansible_host=203.0.113.111
server2 ansible_host=203.0.113.112
server3 ansible_host=203.0.113.113
[all:vars]
ansible_python_interpreter=/usr/bin/python3
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
all:
children:
servers:
hosts:
server1:
ansible_host: 203.0.113.111
ansible_python_interpreter: /usr/bin/python3
server2:
ansible_host: 203.0.113.112
ansible_python_interpreter: /usr/bin/python3
server3:
ansible_host: 203.0.113.113
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.
[webservers]
203.0.113.111
203.0.113.112
[dbservers]
203.0.113.113
server_hostname
[development]
203.0.113.111
203.0.113.113
[production]
203.0.113.112
server_hostname
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/id_rsa.pub [email protected]
$ ssh-copy-id -i $HOME/.ssh/id_rsa.pub [email protected]
$ ssh-copy-id -i $HOME/.ssh/id_rsa.pub [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.
Conclusion
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.