Beginners guide to install Ansible on RHEL/CentOS 8

Written by - Deepak Prasad

In this article I will share Step-by-Step tutorial to install Ansible on RHEL/CentOS 8 Linux environment. We will setup a three node environment with one controller node and two managed nodes. But before we start with the steps to install Ansible on RHEL 8 or CentOS 8, let us understand what is Ansible and how it works (if you don't already know)


What is Ansible and how it works?

Ansible is a modern automation tool that makes our lives easier by helping us manage our servers, deployments, and infrastructure. We declare what we want and let Ansible do the hard work. Some of the things that Ansible can do are as follows:

  • Install and configure software
  • Manage users and databases
  • Deploy applications
  • Remote execution
  • Manage Infrastructure as Code


Ansible has certain distinct advantages over other similar tools.

  • Ansible is agentless. So we do not need to install any software on the servers that are to be managed. It does require Python runtime on the servers and a SSH server on remote hosts.
  • Ansible supports both push and pull modes. So we can execute Ansible code from a central control machine to make changes on remote machines or the remote machines can pull configuration from a well defined source periodically.
  • Code for Ansible is written in YAML ( ), which stands for YAML Ain't Markup Language.
  • Ansible does not try to re-invent the wheel. Hence it uses SSH as a transport and YAML as a Domain Specific Language (DSL).


Lab Environment

I have created three Virtual Machines running on Oracle Virtual Box installed on a Linux Server. One of these VM will be the controller on which we will install ansible while the other two VMs will act as a managed server (client) on which we will perform different tasks using playbook.

Below are the configurations of these 3 VMs:

Configuration Conroller Node Managed Node1 Managed Node2
OS CentOS 8 CentOS 8 CentOS 8
IP Address
rpms required ansible
python3 python3


Step 1: Update /etc/hosts

You can either configure BIND DNS server to resolve hostname or alternatively update /etc/hosts file with the hostname and IP details of your controller and managed hosts in your setup

[root@controller ~]# cat /etc/hosts   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6    controller   server1   server2


Step 2: Install Ansible

I will share the steps to install Ansible on both RHEL and CentOS 8 using different methods:


Method 1: CentOS 8 Install Ansible using EPEL repo

For CentOS 8 install ansible, in this method we will show installation via EPEL repo. First manually install EPEL repo on your CentOS 8 Linux node:

[root@controller ~]# dnf -y install epel-release

Now once epel repo is installed you can search for ansible package

# dnf search ansible
======================================= Name Exactly Matched: ansible =======================================
ansible.noarch : SSH-based configuration management, deployment, and task execution system

So you can now install ansible.noarch rpm on the controller node using dnf or yum

[root@controller ~]# dnf install -y ansible.noarch


Method 2: CentOS 8 Install Ansible using pip

In the next method for CentOS 8 install ansbile you can also use pip. To install ansible via pip install the below rpms on your controller node:

[root@controller ~]# dnf install python3 python3-pip -y

Next install ansible using pip3 as a normal user "deepak"

[deepak@controller ~]$ pip3 install ansible --user
Requirement already satisfied: ansible in /usr/lib/python3.6/site-packages
Requirement already satisfied: jinja2 in /usr/lib/python3.6/site-packages (from ansible)
Requirement already satisfied: PyYAML in /usr/lib64/python3.6/site-packages (from ansible)
Requirement already satisfied: cryptography in /usr/lib64/python3.6/site-packages (from ansible)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/lib64/python3.6/site-packages (from jinja2->ansible)
Requirement already satisfied: idna>=2.1 in /usr/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: asn1crypto>=0.21.0 in /usr/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: six>=1.4.1 in /usr/lib/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: cffi!=1.11.3,>=1.7 in /usr/lib64/python3.6/site-packages (from cryptography->ansible)
Requirement already satisfied: pycparser in /usr/lib/python3.6/site-packages (from cffi!=1.11.3,>=1.7->cryptography->ansible)


Method 3: RHEL 8 Install Ansible

To install ansible on RHEL 8 you must first register your RHEL 8 node. Now I have already registered my RHEL 8 node to Red Hat Network.
Next you can enable the Red Hat Ansible Engine Repository:

# subscription-manager repos --enable ansible-VERSION-for-rhel-8-x86_64-rpms

Currently at the time of writing this article ansible-2.8.5 was the latest

# subscription-manager repos --enable ansible-2.8-for-rhel-8-x86_64-rpms

Next use dnf on RHEL 8 install ansible

# dnf install ansible -y


Based on your environment once you install Ansible, next you can see this will also install python3 as dependency

[root@controller ~]# ansible --version
ansible 2.8.5
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, May 21 2019, 23:51:36) [GCC 8.2.1 20180905 (Red Hat 8.2.1-3)]


Step 3: Install Python on managed nodes

Now we don't need to install ansible on the managed hosts but we must install python3 on all the managed hosts:

You can use dnf to search and install python3 package. I have installed below rpm on both my managed host where dnf will handle all the dependencies

[root@server2 ~]# rpm -qa | grep python36

[root@server1 ~]# rpm -qa | grep python36


Step 4: Create normal user

This is important as we will use this user to perform all ansible related tasks. For the sake of this article I will create a user "ansible"

[root@controller ~]# useradd ansible

Assign a password to this user

[root@controller ~]# passwd ansible

Repeat the same on managed nodes i.e. create the same user on all your managed hosts:

[root@server1 ~]# useradd ansible
[root@server1 ~]# passwd ansible
[root@server2 ~]# useradd ansible
[root@server1 ~]# passwd ansible


Step 5: Create and distribute SSH keys to managed nodes

Now we must enable password less login between our controller node and all the managed hosts. So we can configure passphrase based login using ssh-keygen

Login or switch user to "ansible" and execute ssh-keygen in the below format. With -P we assign a null password to the key pair

[ansible@controller ~]$ ssh-keygen -t rsa -P ""
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_rsa):
Created directory '/home/ansible/.ssh'.
Your identification has been saved in /home/ansible/.ssh/id_rsa.
Your public key has been saved in /home/ansible/.ssh/
The key fingerprint is:
The key's randomart image is:
+---[RSA 2048]----+
|      +o=B=.   o+|
|       @o=Bo  ..o|
|      + B=o* . =+|
|       . .B.= o *|
|        S  B +  o|
|            B  ..|
|           .  o E|
|             . o |
|                 |

This will create public and private key pair in the home directory under ~/.ssh/. Now since we have a public and private key pair, copy public key to target managed server. We use ssh-copy-id as it saves time and performs all the tasks required to enable passphrase based login.

[ansible@controller ~]$ ssh-copy-id server1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ansible/.ssh/"
The authenticity of host 'server1 (' can't be established.
ECDSA key fingerprint is SHA256:RxJuKeoiMc/+4H7IO52YTFOStE3hgd7ulMwjpAVGDZs.
Are you sure you want to continue connecting (yes/no)? 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
ansible@server1's password:

Number of key(s) added: 1

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

Repeat the same for other managed hosts

[ansible@controller ~]$ ssh-copy-id server2

Also copy the public key for localhost on controller node. This will also be required later.

[ansible@controller ~]$ ssh-copy-id controller


Verify password less SSH authentication

The ssh-copy-id command will copy the public key we just created to server1 and server2 and append the content of the key to ansible user's authorized_keys file under ~/.ssh. Here .ssh is a hidden directory.

You can perform a ssh to managed host to make sure you can connect to the server without giving any password or passphrase.

[ansible@controller ~]$ ssh server1
Last login: Wed Jan 29 20:24:46 2020
[ansible@server1 ~]$

So we were able to connect to our server1 managed host without any password here.

Similarly verify SSH from controller to other managed hosts


Step 6: Configure privilege escalation using sudo

Since our ansible user would need privilege escalation we will create a new rule for ansible user using a new file under /etc/sudoers.d

[root@controller ~]# cat /etc/sudoers.d/ansible

Add the same rule on all your managed hosts

[root@server1 ~]# echo "ansible ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/ansible
[root@server2 ~]# echo "ansible ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/ansible


Step 7: Configure Ansible on controller node

After we install ansible let us configure ansible to run some ad-hoc commands.


Create custom project

We will create a project "base" under our home directory:

[ansible@controller ~]$ mkdir base


Create and Configure ansible.cfg

The configuration file for Ansible can exist in a few different locations, where the first file found will be used. The search involves the following:

  • ANSIBLE_CFG: This environment variable is used, provided it is set
  • ansible.cfg: This is located in the current directory
  • ~/.ansible.cfg: This is located in the user's home directory
  • /etc/ansible/ansible.cfg

We will create an ansible.cfg under the base project. In this we identify how to connect remote hosts.

[ansible@controller base]$ cat ansible.cfg
remote_user = ansible          ; use ansible user
host_key_checking = false      
inventory = inventory          ; Inventory file exists in the current directory
log_path = base.log            ; base.log file will be created/used as log file

become = True                  ; Become someone else to perform tasks
become_method = sudo           ; use sudo
become_user = root             ; Become root user
become_ask_pass = False        , Don't ask for password with sudo

inventory argument tells the relative filename which contains the list of managed hosts. So you must create a file "inventory" under your project directory.


Create static inventory file

  • Inventory contains a list of hostname or IP addresses. Although you should avoid using IP Addresses in the inventory
  • ansible.cfg defines how privileges are escalated. You can create this per project or use a generic file
  • It is common to work with project directories that contain these files
  • In Ansible, we have static and dynamic inventory. For now we will only use static inventory
  • Even ad hoc actions performed on the localhost require an inventory, though that inventory may just consist of the localhost.
  • The inventory is the most basic building block of Ansible architecture.
  • When executing ansible or ansible-playbook, an inventory must be referenced. Inventories are either files or directories that exist on the same system that runs ansible or ansible-playbook.
  • The location of the inventory can be referenced at runtime with the --inventory-file (-i) argument, or by defining the path in an Ansible config file.
[ansible@controller base]$ cat inventory

To list the matching hosts using our inventory file use below command. This will not execute any command on the inventory nodes:

[ansible@controller base]$ ansible all --list-hosts
  hosts (2):


Step 8: Running ad-hoc commands

  • Ad hoc commands in Ansible are used to perform tasks or operations that are needed on an ad hoc basis, or only once, based upon the requirement.
  • In other words, these are tasks that a user wants to be performed on the fly but doesn't want to be saved for later use.
  • Ansible modules can be called using ansible command
  • Use ansible-doc -l for a list of modules and ansible-doc <modulename> for information about module options
  • Specify which module to use, using -m
  • The "command" module is default, and does not have to be specified


	ansible all -m command -a id
	ansible all -m shell -a env

In the below ansible example we will check the available memory on our managed hosts using "free -m" command

[ansible@controller base]$ ansible all -m shell -a "free -m" | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           4789         201        4100           8         487        4353
Swap:           955           0         955 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           4789         204        4102           8         482        4350
Swap:           955           0         955

Next we will try to add some content in a file on

[ansible@controller base]$ ansible -m copy -a "content='Hello, My name is deepak' dest=~/hello.txt" | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    "changed": true,
    "checksum": "3fa09515585e1da48417b015f7bd40cd665d9cf2",
    "dest": "/root/hello.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "4f5f6876ea14b5e5d005059b0112dd32",
    "mode": "0644",
    "owner": "root",
    "size": 24,
    "src": "/home/ansible/.ansible/tmp/ansible-tmp-1580546381.2696378-140602648211740/source",
    "state": "file",
    "uid": 0


Lastly I hope the steps from the article to install ansible on RHEL/CentOS 8 Linux was helpful. So, let me know your suggestions and feedback using the comment section.


Learn Ansible

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can reach out to him on his LinkedIn profile or join on Facebook page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to

Thank You for your support!!

2 thoughts on “Beginners guide to install Ansible on RHEL/CentOS 8”

  1. Donot put comments in the ansible.cfg file, otherwise you will get errors like this:

    [ansible@centos8 ~]$ ansible all –list-hosts
    [WARNING]: Unable to parse /home/ansible/inventory # Inventory file exists in the current directory as an inventory source
    [WARNING]: No inventory was parsed, only implicit localhost is available
    [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match ‘all’
    hosts (0):


Leave a Comment