0. Introductions to Ansible
Ansible is an open-source automation tool that allows you to perform actions on multiple servers simultaneously. Using the platform, you can make any changes to target hosts - such as installing software, managing users, performing backups, and much more.
Examples of some tasks that Ansible can handle:
Configuration management. With Ansible you can set up specific infrastrauture on each machine (for example Nginx with created user and copied configuration file). With ansible you you simply write a script once that executes all the steps automatically.
Application deployment. For example, you haveto stop an old version, download new code from Git, install dependencies, and then launch the application. Ansible allows you to deploy new application versions across all servers simultaneously.
Host information gathering. The software can be used to automatically collect data about the device, such as the OS version, RAM, disk, processor, and other system components.
0.1 How Ansible works
The two main Ansible roles:
Control node: main server where Ansible is installed and where you run all the commands. You manage all other servers (managed nodes) from this specific machine.
Managed node: any remote server managed by Ansible.
Ansible controls Linux servers (managed nodes) over SSH, and you only install it on the control node. Managed servers require only SSH access, a user account, and Python, as most Ansible modules depend on it.
0.2 Requirements
A control node running Ubuntu, Debian, AlmaLinux or Rocky Linux;
At least one Linux VPS (managed node);
SSH access to that VPS (SSH key-based login is the safest choice).
In this guide we will have example with one control and these 2 managed nodes:
1. Ubuntu server: 192.0.2.10
2. AlmaLinux server: 192.0.2.20
SSH user (on both managed nodes): adminuser
Replace the IPs and username with your own.
1. Install Ansible
Please note, you have to install Ansible only on the control node.
1.1 Ubuntu
If you run Ubuntu on your control node:
sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y
Note: On Ubuntu, automatic updates may occasionally run in the background and lock the package manager. If you see a Could not get lock /var/lib/dpkg/lock-frontend message, wait for the automatic update process to finish, then run the command sudo apt install ansible -y again. Do not delete the lock file manually.
1.2 Debian
If you run Debian on your control node:
sudo apt update
sudo apt install ansible -y
The version in Ubuntu's repositories can be a bit behind. If you need something newer, the Ansible project has instructions for using their PPA.
1.3 AlmaLinux/Rocky Linux
If you run AlmaLinux or Rocky Linux on your control node, enable the EPEL repository first and then install Ansible:
sudo dnf install epel-release -y
sudo dnf install ansible -y
1.4 Verify installation
ansible --version
If you see information about the installed version of Ansible, it means it has been successfully installed. This server is now your control node.
2. Make sure SSH works
Before starting working with Ansible, make sure you can connect to Ansible via SSH:
Same for the AlmaLinux server:
Once you're in, confirm the user can use sudo:
sudo whoami
It should print root. Then log out:
exit
2.1 Optional: set up SSH keys
The safest and more convenient way to log in via SSH is by using a key. You can generate it on the control node:
ssh-keygen -t ed25519
The default file location is fine, so you can just press Enter. Then copy the key to each managed server:
ssh-copy-id [email protected]
ssh-copy-id [email protected]
Try logging in again. It shouldn't ask for a password anymore.
3. Create a project directory
Make a folder for your Ansible files and move into it:
mkdir -p ~/ansible-lab
cd ~/ansible-lab
4. Create an inventory
The inventory.ini is the file with a list of servers Ansible is allowed to manage. Create the file:
nano inventory.ini
And paste this in:
[ubuntu]
ubuntu1 ansible_host=192.0.2.10 ansible_user=adminuser
[alma]
alma1 ansible_host=192.0.2.20 ansible_user=adminuser
[linux:children]
ubuntu
alma
Save and close the file.
Here's some key moments to understand inventory.ini file content:
ubuntu1is the name Ansible will use for this server. It can be anything you like.ansible_hostis the actual IP address or hostname to connect to. Enter the actual hostname or IP of your VPSansible_useris the SSH user. In our example user is adminuser.
The last block creates a parent group called linux that includes both the ubuntu and alma child groups. This way you can target only Ubuntu servers, only AlmaLinux servers, or all servers in both groups at once.
5. Check the inventory
First, let's try to read the created inventory file:
ansible all -i inventory.ini --list-hosts
You should get something like this:
hosts (2):
ubuntu1
alma1
You can also run these commands with a single group:
ansible ubuntu -i inventory.ini --list-hosts
ansible alma -i inventory.ini --list-hosts
ansible linux -i inventory.ini --list-hosts
Nothing is sent to your servers at this step. Ansible is only reading your inventory file.
Please note. If you will get this error:
ERROR: Ansible could not initialize the preferred locale: unsupported locale setting
then run this:
export LANG=C.UTF-8
export LC_ALL=C.UTF-8
and then repeat the command:
ansible all -i inventory.ini --list-hosts
6. Test the connection
Now test the connection by running this command:
ansible all -i inventory.ini -m ping
If everything is correct, you will see:
ubuntu1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
alma1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Do not confuse this with the standard Linux ping command. The system command checks network connectivity, while the Ansible ping module checks if Ansible can connect via SSH and execute the module on the server.
"changed": false just means Ansible didn't modify anything.
7. Run your first commands
Now you can run ordinary commands on all your managed servers at once:
ansible all -i inventory.ini -a "hostname"
ansible all -i inventory.ini -a "uptime"
ansible all -i inventory.ini -a "df -h"
ansible all -i inventory.ini -a "free -h"
ansible all -i inventory.ini -a "cat /etc/os-release"
If you do not specify a module using the -m flag, Ansible uses the `command` module. Such one-off commands are called ad-hoc commands; they are convenient for performing quick tasks that do not require writing a playbook.
8. Target a specific group
You don't have to hit every server each time. Just swap all for a group name:
ansible ubuntu -i inventory.ini -a "hostname"
ansible alma -i inventory.ini -a "hostname"
ansible linux -i inventory.ini -a "hostname"
Groups will start to matter as your server list will grow. You can later add groups like these and run commands only where they make sense:
[webservers]
[databases]
[monitoring]
9. Run commands as root
Commands like hostname or uptime work fine as a regular user, but quite often you will have to work as root.
First, check which user Ansible is using by default:
ansible all -i inventory.ini -a "whoami"
It will return adminuser in our case. Now add the -b flag together with -K::
ansible all -i inventory.ini -b -K -a "whoami"
The -b option enables privilege escalation, while -K tells Ansible to ask for the sudo password.
You will see:
BECOME password:
Enter the sudo password of your SSH user.
This time you'll get root:
ubuntu1 | CHANGED | rc=0 >>
root
alma1 | CHANGED | rc=0 >>
root
-b turns on become, Ansible's privilege escalation. On a typical Linux server, Ansible logs in as your normal user and then uses sudo to get root.
If a sudo password is not configured for your user, you can run the command without the -K flag.
10. Troubleshooting
10.1 UNREACHABLE
Ansible can't connect. Try a normal SSH login first:
ssh adminuser@SERVER_IP
If that fails as well, check the IP address, SSH port, firewall rules, username and SSH key.
10.2 Permission denied
Usually this happens due to a wrong username or bad password. Check both values. If you are copying the credentials, ensure they are pasted without any spaces before or after the copied text.
10.3 Connection works but -b fails
Test sudo manually on the server:
sudo whoami
If it asks for a password, run your Ansible command with -K.
10.4 Python is missing on the managed server
Most Ubuntu and AlmaLinux installs come with Python already, but if Ansible complains, you have to install it manually. Connect to the managed server via SSH and run the commands below.
Ubuntu/Debian:
sudo apt update
sudo apt install python3 -y
AlmaLinux/Rocky Linux:
sudo dnf install python3 -y
11. Ansible glossary for beginners
Term | Meaning |
Control node | The machine where Ansible is installed and run |
Managed node | A remote server controlled by Ansible |
Host | A single server in the inventory |
Group | A set of hosts |
Inventory | The file with the list of the servers Ansible can manage |
Module | A built-in Ansible action |
Become | Privilege escalation, usually through sudo |
Ad hoc command | A one-time command run without a playbook |
For more information about Ansible, you can refer to the official documentation.
