Note:

  • The following commands are for RockyLinux, RedHat, CentOS, on other distros it will be almost the same.
  • I’ve made the choice to connect to a user called ansible, and inside his home directory I’ve created a directory called ansible, in which I will initiate the virtual environment via pipenv (you should have read https://nicodevlog.com/2022/05/17/python-and-virtual-environments-on-linux-os/)

Introduction: python and ansible

Ansible has been written in python language and require python to be executed. It means that on your target hosts you need python installed. Any ansible operation requires python on the target node except the raw and script modules.
Also, most of ansible modules are written in python and also need python on the OS.

Ansible-core vs Ansible community

Since ansible 2.9, ansible distinguish ansible-core from ansible community.

Later in this post, when you will execute pipenv install ansible (or pip install ansible in case you use pip), you will install ansible community which includes:

  • ansible-core (the command line interface tool + builtin plugins and modules)
  • thousands of plugins and modules (grouped by collections)

As you understand ansible community (or if you prefer ‘ansible’) contains ansible-core plus thousands of plugin and modules.

Ansible-core allow to developers to only work on the heart of ansible, and it’s easily maintanable because you can make merges only on ansible-core in case of corrections/evolutions. Also, it could be used to have only a set of plugins and modules that are useful for you, and then have a light installation.

Ansible-core contains a minimal amount of plugins and modules, you can see all the modules and plugins contained in the ansible-core here (it’s the ansible.builtin collection): https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html

If you want to refer to the distinct documentations of ansible-core and ansibile community just go to the home page https://docs.ansible.com and choose the one you want to dive into.

Notes:

Installing ansible 5 inside python virual environment

First you need to have a recent version of python avaible on your server.

Refer to the following post to install python 3.10.4 on your Linux OS and to understand how to create virtual environment in python: https://nicodevlog.com/2022/05/17/python-and-virtual-environments-on-linux-os/

To see which version of ansible community package is available to install you can go to pypi (python package installer), and type “ansible” and you’ll find this.

At the time of this writing, the version is ansible 5.8.0 (avaible since the 18th of may 2022)

Suppose you are a root user (or a sudo user):

yum -y install sshpass # sshpass is used by ansible in cases you define a ssh connection with login and password
pip3.10 install pipenv
useradd ansible # and set your ansible password
su - ansible
mkdir ansible
cd ansible
pipenv --python 3.10 # create a virtual environment that uses python 3.10.x
pipenv install ansible # install python inside the virtual environment
[ansible@ansible ansible]$ pipenv run ansible --version
ansible [core 2.12.5]
  config file = None
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ansible/.local/share/virtualenvs/ansible-ZNHM7g56/lib/python3.10/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ansible/.local/share/virtualenvs/ansible-ZNHM7g56/bin/ansible
  python version = 3.10.4 (main, May 16 2022, 10:31:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-4)]
  jinja version = 3.1.2
  libyaml = True
[ansible@ansible ansible]$ ls
Pipfile  Pipfile.lock

Ansible quick start

First create an inventory file in order to reference the ansible target nodes. In this example we will use a basic authentication with login and password to linux and windows machines. Note that for windows machines you’ll need winrm installed.

But there are better ways to connect to your hosts like with ssh keys for linux, and the equivalent of ssh keys with kerberos configured on your windows hosts.

For example here a simple inventory that you call hosts.yml and put something like this:

# Here you list all your connections
web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password
web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password
web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password
web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password
api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password

# [web] allow you to group/tag your hosts
[web]
web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password
web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password
web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password
web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password

[notweb]
api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password

[mylinux]
web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password
web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password
web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password
api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password

[mywin]
web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password

You can test your hosts.yml by usind the builtin module ping (present inside ansible-core). For example here we ping the host referenced as web1 inside our inventory hosts.yml:

pipenv run ansible -i ./hosts.yml -m ping web1

To avoid specifying each time where is located your inventory, with the option -i, you can create an ansible configuration file named ansible.cfg

When you are inside your project directory, where you’ve executed pipenv to create the virtual environment, create an ansible.cfg file in which you will specify. You’ll then will have:

[ansible@ansible ansible]$ ls
ansible.cfg  hosts.yml  Pipfile  Pipfile.lock

Why there?

By default ansible will look for this file and read it if present, ansible will search in this order:

  • ANSIBLE_CONFIG (an environment variable)
  • Current directory
  • Ansible Home directory
  • /etc/ansible/ansible.cfg

Then in my case I’m connected to the user ansible, and in his home directory I’ve created a directory ansible inside which I’ve initiated the virtual environment. The for ansible the current directory is /home/ansible/ansible

Inside this file you also have to specify host_key_checking = false to avoir the error that indicated that you ansible server doesn’t know the target host (it means the finger print of the target host is not inside the ~/.ssh/known_hosts file):

[defaults]
host_key_checking = false
inventory = ./hosts.yml

Avoid use ssh connection on a root user

For several security reasons, you should instead connect to a sudo user if you need some root permissions:

  • On the target host you’ll be able to make the distinction between root user and the sudo user used by ansible (history, process started by, …)
  • you can define fine-grained permissions to your sudo user