{"id":22176,"date":"2024-04-19T23:47:48","date_gmt":"2024-04-19T20:47:48","guid":{"rendered":"https:\/\/kifarunix.com\/?p=22176"},"modified":"2024-04-20T08:00:51","modified_gmt":"2024-04-20T05:00:51","slug":"easy-way-to-install-ansible-on-ubuntu-24-04","status":"publish","type":"post","link":"https:\/\/kifarunix.com\/easy-way-to-install-ansible-on-ubuntu-24-04\/","title":{"rendered":"Easy way to Install Ansible on Ubuntu 24.04"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1061\" height=\"595\" src=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux.png\" alt=\"Install and Setup Ansible on Ubuntu\" class=\"wp-image-15512\" title=\"\" srcset=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux.png 1061w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux-768x431.png 768w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux-150x84.png 150w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux-300x168.png 300w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux-696x390.png 696w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/06\/install-ansible-linux-749x420.png 749w\" sizes=\"(max-width: 1061px) 100vw, 1061px\" \/><\/figure>\n\n\n\n<p>In this tutorial, we are going to learn how to install Ansible on Ubuntu 24.04. <a href=\"https:\/\/www.ansible.com\/overview\/it-automation\" target=\"_blank\" rel=\"noreferrer noopener\">Ansible<\/a> is a simple agentless IT automation tool. It handles configuration management, application deployment, cloud provisioning, ad-hoc task execution, network automation, and multi-node orchestration over the SSH protocol. Ansible makes easy to automate repetitive tasks.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#basic-ansible-concepts-architecture\">Basic Ansible Concepts\/Architecture<\/a><\/li><li><a href=\"#installing-ansible-on-ubuntu-24-04\">Installing Ansible on Ubuntu 24.04<\/a><ul><li><a href=\"#run-system-update\">Run System Update<\/a><\/li><li><a href=\"#install-ansible-on-ubuntu-24-04\">Install Ansible on Ubuntu 24.04<\/a><ul><li><a href=\"#install-ansbile-using-pip-on-ubuntu\">Install Ansbile using PIP on Ubuntu<\/a><\/li><li><a href=\"#install-ansible-using-apt-package-manager\">Install Ansible using APT Package Manager<\/a><\/li><\/ul><\/li><li><a href=\"#setup-ansible-on-control-node\">Setup Ansible on Control Node<\/a><ul><li><a href=\"#running-ansible-installed-system-wide-and-python-virtualenv\">Running Ansible Installed System-Wide and Python Virtualenv<\/a><\/li><li><a href=\"#configure-ansible-inventory\">Configure Ansible Inventory<\/a><\/li><\/ul><\/li><li><a href=\"#setup-ansible-ssh-key-authentication\">Setup Ansible SSH key authentication<\/a><ul><li><a href=\"#generate-ssh-keys\">Generate SSH Keys<\/a><\/li><li><a href=\"#copy-ssh-public-keys-to-managed-hosts\">Copy SSH Public keys to Managed Hosts<\/a><\/li><li><a href=\"#test-ansible-connection-to-remote-hosts\">Test Ansible Connection to Remote Hosts<\/a><\/li><\/ul><\/li><li><a href=\"#running-ansible-ad-hoc-commands\">Running Ansible ad-hoc commands<\/a><\/li><li><a href=\"#using-ansible-playbooks\">Using Ansible Playbooks<\/a><ul><li><a href=\"#ansible-playbook-to-create-user-account\">Ansible Playbook to Create User Account<\/a><\/li><li><a href=\"#ansible-playbook-to-install-apache-web-server\">Ansible Playbook to Install Apache Web server<\/a><\/li><li><a href=\"#running-ansible-playbook-dry-run-checks\">Running Ansible Playbook Dry Run checks<\/a><\/li><li><a href=\"#executing-ansible-playbook\">Executing Ansible Playbook<\/a><\/li><li><a href=\"#verify-user-account-creation-and-package-installed-using-ansible\">Verify User Account Creation and Package installed using Ansible<\/a><\/li><\/ul><\/li><li><a href=\"#further-reading\">Further Reading<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"basic-ansible-concepts-architecture\">Basic Ansible Concepts\/Architecture<\/h2>\n\n\n\n<p>Ansible automation tool is made up various components. So, what are these components that makes up Ansible?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Control Node<\/strong>: As you already know, Ansible is used to automate various tasks on your infrastructure nodes. As such, Ansible has to be installed on one node that is then used to connect to (via SSH) and orchestrate tasks on the remote nodes. The node on which you install Ansible, becomes the <strong><code>control node<\/code><\/strong>.<\/li>\n\n\n\n<li><strong>Managed Node<\/strong>: Ansible managed node refers to nodes that Ansible will connect to and execute various tasks or commands on them. They can be virtual machines, physical servers, or any other systems that you can be connected to via SSH.<\/li>\n\n\n\n<li><strong>Inventory<\/strong>: Ansible inventory is file that lists managed hosts, either individually or as grouped hosts depending on a common role. As such, inventory defines hostnames or IP addresses of the managed nodes, along with any variables or groupings.<\/li>\n\n\n\n<li><strong>Playbooks<\/strong>: Ansible playbooks are YAML files that define a set of tasks, here in called plays, that are meant for execution on the managed hosts. They are execute one by one, and in the order they are defined, against all or specific hosts in the inventory. &#8220;<em>playbooks are made up of plays; plays are made up of tasks<\/em>&#8220;.<\/li>\n\n\n\n<li><strong>Tasks<\/strong>: Ansible tasks define specific actions or commands to be executed against all or specific subset of hosts defined in the inventory. Tasks can include actions to install packages, manage files, start or stop services, run scripts, &#8230;<\/li>\n\n\n\n<li><strong>Modules<\/strong>: Ansible modules are the building blocks of Ansible. They represent small Python codes that does the actual execution of the tasks defined in the Ansible playbooks on managed hosts. They contain metadata that defines when and where a specific automation task is executed and which users can execute it. By default, Ansible provides a large collection of built-in modules, that facilitates execution of a wide range of tasks.<\/li>\n\n\n\n<li><strong>Plugins<\/strong>: Ansible <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/plugins\/plugins.html\" target=\"_blank\" rel=\"noreferrer noopener\">plugins<\/a> are used together with Ansible modules extend the functionality of Ansible.<\/li>\n\n\n\n<li><strong>Handlers<\/strong>: Ansible handlers are used to define specific actions to be taken whenever Ansible tasks meet specific condition. For example, you can define an handler to restart application service whenever a change is made to that application configuration.<\/li>\n\n\n\n<li><strong>Roles<\/strong>: You can think of Ansible roles define a group related tasks, variables, templates, and other Ansible resources in a standard directory structure.<\/li>\n\n\n\n<li><strong>Ansible Vault<\/strong>: It is possible that some of your Ansible tasks requires sensitive information such as credentials to perform specific action. Such sensitive information can be securely stored in an Ansible vault in an encrypted format.<\/li>\n\n\n\n<li><strong>Variables<\/strong>: Ansible uses variables to store values that can be re-used across Ansible tasks\/playbooks.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"installing-ansible-on-ubuntu-24-04\">Installing Ansible on Ubuntu 24.04<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"run-system-update\">Run System Update<\/h3>\n\n\n\n<p>Before you can proceed, ensure that your system package cache is up-to-date;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt update<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"install-ansible-on-ubuntu-24-04\">Install Ansible on Ubuntu 24.04<\/h3>\n\n\n\n<p>There different methods you can use to install Ansible on Ubuntu 24.04 systems;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"#install-ansbile-with-pip\">Install Ansbile using PIP on Ubuntu<\/a><\/li>\n\n\n\n<li><a href=\"#install-ansible-via-apt\">Install Ansible using APT Package Manager<\/a><\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"install-ansbile-using-pip-on-ubuntu\">Install Ansbile using PIP on Ubuntu<\/h4>\n\n\n\n<p>To install Ansbile using Python PIP command, install PIP before you can proceed;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install python3-pip python3-venv<\/code><\/pre>\n\n\n\n<p>If PIP is already installed, you can upgrade it;<\/p>\n\n\n\n<p>However, recent versions of Python PIP now discourages glabol Python package installation or removal for the purposes of ensuring system stability. As a result, it encourages the installation of Python packages on user virtual environment. Read more on <a href=\"https:\/\/peps.python.org\/pep-0668\/\" target=\"_blank\" rel=\"noreferrer noopener\">PEP 668<\/a>.<\/p>\n\n\n\n<p>As a result, create your Python virtual environment where you can have control of what Python packages you can ins without introducing any conflicts with other system-wide Python installations.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 -m venv ansible<\/code><\/pre>\n\n\n\n<p>This will create a self contained Ansible Python Virtual environment in the current working directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -1 ansible<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>bin\ninclude\nlib\nlib64\npyvenv.cfg\n<\/code><\/pre>\n\n\n\n<p>Next, activate your Python virtual environment and upgrade PIP (if it needs upgrade);<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>source ansible\/bin\/activate<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 -m pip install --upgrade pip<\/code><\/pre>\n\n\n\n<p>Then install Ansbile for the current user only by running the command below;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 -m pip install ansible<\/code><\/pre>\n\n\n\n<p>All the Ansible binaries are installed in &#8216;<strong><code>$HOME\/ansible\/bin<\/code><\/strong>&#8216;. As a result, you can only access Ansible when you login and activate the users Python virtual environment created above.<\/p>\n\n\n\n<p>Check Ansible version;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible --version<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>ansible [core 2.16.6]\n  config file = None\n  configured module search path = ['\/home\/kifarunix\/.ansible\/plugins\/modules', '\/usr\/share\/ansible\/plugins\/modules']\n  ansible python module location = \/home\/kifarunix\/ansible\/lib\/python3.12\/site-packages\/ansible\n  ansible collection location = \/home\/kifarunix\/.ansible\/collections:\/usr\/share\/ansible\/collections\n  executable location = \/home\/kifarunix\/ansible\/bin\/ansible\n  python version = 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] (\/home\/kifarunix\/ansible\/bin\/python3)\n  jinja version = 3.1.3\n  libyaml = True\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"install-ansible-using-apt-package-manager\">Install Ansible using APT Package Manager<\/h4>\n\n\n\n<p>Ubuntu default repos provides Ansible packages. However, such packages may not be up-to-date.<\/p>\n\n\n\n<p>To check available versions of the Ansible package, run the command below;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt-cache policy ansible<\/pre>\n\n\n\n<p>Sample output from Ubuntu 24.04;<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>ansible:\n  Installed: (none)\n  Candidate: 9.2.0+dfsg-0ubuntu5\n  Version table:\n     9.2.0+dfsg-0ubuntu5 500\n        500 http:\/\/de.archive.ubuntu.com\/ubuntu noble\/universe amd64 Packages\n<\/code><\/pre>\n\n\n\n<p>Read more on <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/reference_appendices\/release_and_maintenance.html#ansible-community-changelogs\" target=\"_blank\" rel=\"noreferrer noopener\">Ansible changelogs<\/a>.<\/p>\n\n\n\n<p>The most recent version of Ansible provided by the default Ubuntu 24.04 repositories as of this writing is v9.4.0.<\/p>\n\n\n\n<p>You can install the latest version from the Ansible PPA repositories. However, Ubuntu 24.04, Noble Numbat PPA repos are currently unavailable.<\/p>\n\n\n\n<p>As such, install Ansible from the default Ubuntu 24.04 repositories.<\/p>\n\n\n\n<p>You can then install Ansible by executing the command below;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt install ansible<\/pre>\n\n\n\n<p>Once the installation is done, you can check the version of install Ansible as follows;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>ansible --version<\/code><\/pre>\n\n\n\n<p>When the <a href=\"https:\/\/ppa.launchpadcontent.net\/ansible\/ansible\/ubuntu\/dists\/\" target=\"_blank\" rel=\"noreferrer noopener\">PPA repos for Ubuntu 24.04<\/a> are available, you can install latest Ansible release versions by running the commands;<\/p>\n\n\n\n<blockquote class=\"wp-block-quote has-small-font-size is-layout-flow wp-block-quote-is-layout-flow\">\n<pre class=\"wp-block-code\"><code><em>sudo apt -y install software-properties-common<\/em><\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><em>sudo apt-add-repository ppa:ansible\/ansible --yes<\/em><\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><em>sudo apt update<\/em><\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><em>sudo apt install ansible<\/em><\/code><\/pre>\n<cite>Installing Ansible on Ubuntu 24.04 from PPA repos<\/cite><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setup-ansible-on-control-node\">Setup Ansible on Control Node<\/h3>\n\n\n\n<p>Now that Ansible is installed on an Ubuntu 24.04 control node, it is time to set it up to enable you automate deployment of your tasks on the managed remote hosts via SSH protocol.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"running-ansible-installed-system-wide-and-python-virtualenv\">Running Ansible Installed System-Wide and Python Virtualenv<\/h4>\n\n\n\n<p>If you have installed Ansible system-wide, then you can run normally because all required binaries must already be on the path.<\/p>\n\n\n\n<p>If you are running Ansible on a user&#8217;s Python virtual environment, then you must activate that virtual environment for you to access Ansible binaries.<\/p>\n\n\n\n<p>For example, our user&#8217;s Ansible virtual env is, <strong>~\/ansible<\/strong>. To activate this environment;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>source ~\/ansible\/bin\/activate<\/code><\/pre>\n\n\n\n<p>After that, you should be able to now use Ansible normally.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"configure-ansible-inventory\">Configure Ansible Inventory<\/h4>\n\n\n\n<p>If you have installed <code>\/etc\/ansible\/hosts<\/code> is the default Ansible inventory file. It is also possible to define a custom file as your Ansible inventory file. When you use a non-default inventory file, you have to specify the path to it with <code>-<strong>i &lt;path&gt;<\/strong><\/code> option while running ansible.<\/p>\n\n\n\n<p>In the inventory file:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>you can specify the details of the hosts using resolvable hostnames or IP addresses,<\/li>\n\n\n\n<li>A group of hosts are delimited by <code>[header]<\/code> elements<\/li>\n\n\n\n<li>A hostname\/IP address can be a member of multiple groups<\/li>\n<\/ul>\n\n\n\n<p>See examples below to create a hosts file with ungrouped hosts, grouped hosts and a range of hosts.<\/p>\n\n\n\n<p>In this tutorial, I will create my inventory in my home directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>mkdir -p $HOME\/etc\/ansible<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>vim $HOME\/etc\/ansible\/hosts<\/code><\/pre>\n\n\n\n<p><strong>NOTE: Any individual host, (Ungrouped hosts),should be specified before any group headers.<\/strong><\/p>\n\n\n\n<pre class=\"scroll-box\"><code>\n# Ungrouped list of hosts\nserver01.kifarunix-demo.com\n192.168.122.92\n\n# Range of hosts\n192.168.122.[111:112]\n\n[webapps]\napp[01:04].kifarunix-demo.com\n\n# Grouped Hosts\n[database]\ndb[01:03].kifarunix-demo.com\ndb05.kifarunix-demo.com\ndb07.kifarunix-demo.com\n<\/code><\/pre>\n\n\n\n<p>Save and exit the file.<\/p>\n\n\n\n<p>You can list the hosts in your inventory using the <code>ansible-inventory<\/code> command. For example, to display the contents of our hosts list above in YAML format;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-inventory -i $HOME\/etc\/ansible\/hosts --list -y<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>all:\n  children:\n    database:\n      hosts:\n        db01.kifarunix-demo.com: {}\n        db02.kifarunix-demo.com: {}\n        db03.kifarunix-demo.com: {}\n        db05.kifarunix-demo.com: {}\n        db07.kifarunix-demo.com: {}\n    ungrouped:\n      hosts:\n        192.168.122.111: {}\n        192.168.122.112: {}\n        192.168.122.92: {}\n        server01.kifarunix-demo.com: {}\n    webapps:\n      hosts:\n        app01.kifarunix-demo.com: {}\n        app02.kifarunix-demo.com: {}\n        app03.kifarunix-demo.com: {}\n        app04.kifarunix-demo.com: {}\n<\/code><\/pre>\n\n\n\n<p>Read more on <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_inventory.html#intro-inventory\" target=\"_blank\">how to build ansible inventory<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setup-ansible-ssh-key-authentication\">Setup Ansible SSH key authentication<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"generate-ssh-keys\">Generate SSH Keys<\/h4>\n\n\n\n<p>Ansible uses SSH to connect to managed hosts. Use of SSH key authentication (usually passwordless) is one of the common methods that by default Ansible uses for managing remote hosts. It is also possible to have Ansible use username\/password authentication to connect to managed hosts,however not generally recommended.<\/p>\n\n\n\n<p>Therefore, you need to generate passwordless SSH key and copy the keys to the remote hosts your want to manage with Ansible.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ssh-keygen<\/pre>\n\n\n\n<p>For passwordless SSH key generation, simply press ENTER for empty password.<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>Generating public\/private ed25519 key pair.\nEnter file in which to save the key (\/home\/kifarunix\/.ssh\/id_ed25519): \nEnter passphrase (empty for no passphrase): \nEnter same passphrase again: \nYour identification has been saved in \/home\/kifarunix\/.ssh\/id_ed25519\nYour public key has been saved in \/home\/kifarunix\/.ssh\/id_ed25519.pub\nThe key fingerprint is:\nSHA256:7qHPByiZZuog9Z3IRgTBhd0aKQ8wuXgBoh0EZZ98tVg kifarunix@noble\nThe key's randomart image is:\n+--[ED25519 256]--+\n|*OB=.o  E        |\n|++*=+..+ .       |\n|o..==oo .        |\n|o ..o.           |\n| .. .o .S        |\n| . +*o.o.        |\n|o  +=.o o.       |\n|....   + ..      |\n| ..   ..+.       |\n+----[SHA256]-----+\n<\/code><\/pre>\n\n\n\n<p>Read more about other connection methods on <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/plugins\/connection.html\" target=\"_blank\">Ansible connection plugins<\/a> page.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"copy-ssh-public-keys-to-managed-hosts\">Copy SSH Public keys to Managed Hosts<\/h4>\n\n\n\n<p>Next, copy the keys to the remote hosts. <strong>Use a remote user with sudo rights.<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">for i in 192.168.122.11 192.168.122.92; do ssh-copy-id -o StrictHostKeyChecking=no johndoe@$i; done<\/pre>\n\n\n\n<p>In this demo, we will be using a user with passwordless sudo rights. To enable a user to run commands with sudo without being prompted for password, run the command below on the remote hosts being managed.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo EDITOR=vim visudo \/etc\/sudoers.d\/johndoe<\/pre>\n\n\n\n<p>Paste the following, replacing the usernames accordingly;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>johndoe ALL=(ALL:ALL) NOPASSWD: ALL<\/code><\/pre>\n\n\n\n<p>Save and exit the file.<\/p>\n\n\n\n<p>Read more on <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/become.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Ansible privileges escalation page<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"test-ansible-connection-to-remote-hosts\">Test Ansible Connection to Remote Hosts<\/h4>\n\n\n\n<p>Ansible uses ping module to verify the reachability to the remote hosts defined on the inventory file. Below is our test inventory;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-inventory -i $HOME\/etc\/ansible\/hosts --list -y<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>all:\n  children:\n    centos:\n      hosts:\n        192.168.122.11: {}\n    ubuntu:\n      hosts:\n        192.168.122.92: {}\n<\/code><\/pre>\n\n\n\n<p>To test the connection, as user <strong><code>johndoe<\/code><\/strong>, whose keys we copied above;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible -i $HOME\/etc\/ansible\/hosts -m ping -u johndoe all<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>192.168.122.11 | SUCCESS => {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": false,\n    \"ping\": \"pong\"\n}\n192.168.122.92 | SUCCESS => {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": false,\n    \"ping\": \"pong\"\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"running-ansible-ad-hoc-commands\">Running Ansible ad-hoc commands<\/h3>\n\n\n\n<p>If you have tasks that you would rarely repeat, ad-hoc commands come in so handy. With ad-hoc commands, you can manage user accounts, services, packages, run ad-hoc system commands like check free RAM, gather system facts.<\/p>\n\n\n\n<p>To see a few examples, check if the remote systems have internet connectivity using ping command;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> ansible -i $HOME\/etc\/ansible\/hosts -a \"ping 8.8.8.8 -c 3\" all -u johndoe<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>192.168.122.11 | CHANGED | rc=0 >>\nPING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=5.06 ms\n64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=5.71 ms\n64 bytes from 8.8.8.8: icmp_seq=3 ttl=59 time=5.35 ms\n\n--- 8.8.8.8 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 2003ms\nrtt min\/avg\/max\/mdev = 5.061\/5.370\/5.706\/0.263 ms\n192.168.122.92 | CHANGED | rc=0 >>\nPING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=5.12 ms\n64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=5.22 ms\n64 bytes from 8.8.8.8: icmp_seq=3 ttl=59 time=5.26 ms\n\n--- 8.8.8.8 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 2003ms\nrtt min\/avg\/max\/mdev = 5.121\/5.199\/5.258\/0.057 ms\n<\/code><\/pre>\n\n\n\n<p>To check free memory;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible -i $HOME\/etc\/ansible\/hosts -a \"free -h\" all -u johndoe<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>192.168.122.92 | CHANGED | rc=0 >>\n               total        used        free      shared  buff\/cache   available\nMem:           3.8Gi       268Mi       1.4Gi       1.0Mi       2.1Gi       3.3Gi\nSwap:          2.1Gi          0B       2.1Gi\n192.168.122.11 | CHANGED | rc=0 >>\n               total        used        free      shared  buff\/cache   available\nMem:           1.2Gi       316Mi       827Mi       6.0Mi       278Mi       955Mi\nSwap:             0B          0B          0B\n<\/code><\/pre>\n\n\n\n<p>To install a package, for example a vim editor, as user <code><strong>johndoe<\/strong><\/code> with sudo rights (<code><strong><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/become.html#using-become\" target=\"_blank\" rel=\"noreferrer noopener\">--become<\/a><\/strong><\/code>);<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible -i $HOME\/etc\/ansible\/hosts -m apt -a \"name=vim state=present\" all -u johndoe --become<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible -i $HOME\/etc\/ansible\/hosts -m yum -a \"name=vim state=present\" centos -u johndoe --become<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>192.168.122.11 | CHANGED => {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": true,\n    \"msg\": \"\",\n    \"rc\": 0,\n    \"results\": [\n        \"Installed: vim-filesystem-2:8.2.2637-20.el9.noarch\",\n        \"Installed: vim-common-2:8.2.2637-20.el9.x86_64\",\n        \"Installed: gpm-libs-1.20.7-29.el9.x86_64\",\n        \"Installed: vim-enhanced-2:8.2.2637-20.el9.x86_64\"\n    ]\n}\n<\/code><\/pre>\n\n\n\n<p>Read more about ad-hoc commands on <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_adhoc.html#intro-adhoc\" target=\"_blank\" rel=\"noreferrer noopener\">Introduction to ad-hoc commands<\/a>.<\/p>\n\n\n\n<p>If you want to auto-detect the package manager, simply use package module against all hosts;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible -i $HOME\/etc\/ansible\/hosts <strong>-m package<\/strong> -a \"name=vim state=present\" all -u johndoe --become<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>192.168.122.11 | SUCCESS => {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": false,\n    \"msg\": \"Nothing to do\",\n    \"rc\": 0,\n    \"results\": []\n}\n192.168.122.92 | SUCCESS => {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"cache_update_time\": 1713503759,\n    \"cache_updated\": false,\n    \"changed\": false\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"using-ansible-playbooks\">Using Ansible Playbooks<\/h3>\n\n\n\n<p>Playbooks are Ansible\u2019s configuration, deployment, and orchestration language.&nbsp;They define roles and tasks (a set of steps to take to set up a specific process) to be executed on the remote hosts.<\/p>\n\n\n\n<p>In this demo, we will cover two simple examples of playbooks;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#ansibleplaybookcreateuseraccount\">To create a user account<\/a><\/li>\n\n\n\n<li><a href=\"#installapachewithansible\">To install a package<\/a><\/li>\n<\/ul>\n\n\n\n<p>So before we can proceed, create Ansible roles directory. Ansible Roles defines a collections of variables, tasks, files, templates and any other ansible artefacts.<\/p>\n\n\n\n<p>For our example, we will have two roles, <code>useraccount<\/code> and <code>apache<\/code>, for defining what user account to create and the package to be installed.<\/p>\n\n\n\n<p>Below is our simple sample Roles directory structure;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tree myplaybooks<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>myplaybooks\/\n\u251c\u2500\u2500 main.yml\n\u2514\u2500\u2500 roles\n    \u251c\u2500\u2500 useraccounts\n    \u2502\u00a0\u00a0 \u2514\u2500\u2500 tasks\n    \u2502\u00a0\u00a0     \u2514\u2500\u2500 main.yml\n    \u2514\u2500\u2500 webserver\n        \u2514\u2500\u2500 tasks\n            \u2514\u2500\u2500 main.yml\n\n6 directories, 3 files\n<\/code><\/pre>\n\n\n\n<p>To create the relevant directories as per above structure;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mkdir -p myplaybooks\/roles\/{useraccounts,webserver}\/tasks<\/pre>\n\n\n\n<p>Create master playbook, <strong>main.yml<\/strong> to define values that will be applicable to all other tasks;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim myplaybooks\/main.yml<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>---\n#\n# A common Playbook to Create a user accounts.\n#\n- hosts: all \n  remote_user: johndoe\n  become: yes\n  roles:\n  - useraccounts\n  - webserver\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"ansible-playbook-to-create-user-account\">Ansible Playbook to Create User Account<\/h4>\n\n\n\n<p>The playbook for creating user account is as per my roles directory structure above. So create a file in which you will define particulars of a user to be created.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim myplaybooks\/roles\/useraccounts\/tasks\/main.yml<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>---\n#\n# Create a user account\n#\n- name: Add User Jane Doe to the system\n  user:\n          name: janedoe\n          password: \"{{ 'strongpassword' | password_hash('sha512_crypt', 65534) }}\"\n          groups: \"{{ 'sudo' if ansible_distribution == 'Ubuntu' else 'wheel' }}\"\n          shell: \/bin\/bash\n          comment: Jane Doe\n          expires: 1584993090\n<\/code><\/pre>\n\n\n\n<p>Ensure passlib for hashing the password is installed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install passlib<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"ansible-playbook-to-install-apache-web-server\">Ansible Playbook to Install Apache Web server<\/h4>\n\n\n\n<p>Similarly, create task file for installing Apache web server on systems;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim myplaybooks\/roles\/webserver\/tasks\/main.yml<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>---\n#\n# Install Apache Web server on CentOS 9\n#\n- name: Install Apache HTTP Server on CentOS\n  ansible.builtin.package:\n    name: httpd\n    state: latest\n  when: ansible_distribution == 'CentOS'\n\n- name: Install Apache2 on Ubuntu\/Debian\n  ansible.builtin.package:\n    name: apache2\n    state: latest\n  when: ansible_distribution in ['Ubuntu', 'Debian']\n<\/code><\/pre>\n\n\n\n<p>To list master Ansible Playbook tasks;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-playbook myplaybooks\/main.yml --list-tasks -i etc\/ansible\/hosts<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\nplaybook: myplaybooks\/main.yml\n\n  play #1 (all): all\tTAGS: []\n    tasks:\n      useraccounts : Add User Jane Doe to the system\tTAGS: []\n      webserver : Install Apache HTTP Server on CentOS\tTAGS: []\n      webserver : Install Apache2 on Ubuntu\/Debian\tTAGS: []\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"running-ansible-playbook-dry-run-checks\">Running Ansible Playbook Dry Run checks<\/h4>\n\n\n\n<p>To check your playbook without making any changes on the remote host, use the <code>--check<\/code> option.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-playbook myplaybooks\/main.yml --check -i etc\/ansible\/hosts<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\nPLAY [all] ************************************************************************************************************************************************************************\n\nTASK [Gathering Facts] ************************************************************************************************************************************************************\nok: [192.168.122.11]\nok: [192.168.122.92]\n\nTASK [useraccounts : Add User Jane Doe to the system] *****************************************************************************************************************************\nchanged: [192.168.122.92]\nchanged: [192.168.122.11]\n\nTASK [webserver : Install Apache HTTP Server on CentOS] ***************************************************************************************************************************\nskipping: [192.168.122.92]\nchanged: [192.168.122.11]\n\nTASK [webserver : Install Apache2 on Ubuntu\/Debian] *******************************************************************************************************************************\nskipping: [192.168.122.11]\nchanged: [192.168.122.92]\n\nPLAY RECAP ************************************************************************************************************************************************************************\n192.168.122.11             : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   \n192.168.122.92             : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0  \n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"executing-ansible-playbook\">Executing Ansible Playbook<\/h4>\n\n\n\n<p>Once you have verified that there is not error with the checks above, proceed to execute the playbook;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-playbook myplaybooks\/main.yml -i etc\/ansible\/hosts<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>PLAY [all] ************************************************************************************************************************************************************************\n\nTASK [Gathering Facts] ************************************************************************************************************************************************************\nok: [192.168.122.11]\nok: [192.168.122.92]\n\nTASK [useraccounts : Add User Jane Doe to the system] *****************************************************************************************************************************\nchanged: [192.168.122.92]\nchanged: [192.168.122.11]\n\nTASK [webserver : Install Apache HTTP Server on CentOS] ***************************************************************************************************************************\nskipping: [192.168.122.92]\nchanged: [192.168.122.11]\n\nTASK [webserver : Install Apache2 on Ubuntu\/Debian] *******************************************************************************************************************************\nskipping: [192.168.122.11]\nchanged: [192.168.122.92]\n\nPLAY RECAP ************************************************************************************************************************************************************************\n192.168.122.11             : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   \n192.168.122.92             : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 \n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"verify-user-account-creation-and-package-installed-using-ansible\">Verify User Account Creation and Package installed using Ansible<\/h4>\n\n\n\n<p>You can create yet another master playbook to verify if user account for <strong>janedoe<\/strong> is created as well as checking is Apache is installed by checking its service if available. Both of these can be checked using <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/modules\/getent_module.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Ansible getent module<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">vim myplaybooks\/check.yml<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>---\n- hosts: all\n  remote_user: johndoe\n  become: yes\n  gather_facts: yes\n  tasks:\n          - name: Gather service facts\n            ansible.builtin.service_facts:\n\n          - name: Check if user Jane Doe (janedoe) is created.\n            getent:\n                  database: passwd\n                  key: janedoe\n          - name: Check if Apache service on CentOS 9.\n            getent:\n                  database: services\n                  key: http\n            when: ansible_distribution == 'CentOS'\n\n          - name: Check if Apache service on Ubuntu.\n            ansible.builtin.debug:\n              msg: \"Apache service is {{ 'present' if 'apache2' in ansible_facts.services.keys() else 'not present' }}\"\n            when: ansible_distribution in ['Ubuntu', 'Debian']\n<\/code><\/pre>\n\n\n\n<p>Execute the playbook;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ansible-playbook myplaybooks\/check.yml -i etc\/ansible\/hosts<\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\nPLAY [all] ************************************************************************************************************************************************************************\n\nTASK [Gathering Facts] ************************************************************************************************************************************************************\nok: [192.168.122.11]\nok: [192.168.122.92]\n\nTASK [Gather service facts] *******************************************************************************************************************************************************\nok: [192.168.122.11]\nok: [192.168.122.92]\n\nTASK [Check if user Jane Doe (janedoe) is created.] *******************************************************************************************************************************\nok: [192.168.122.92]\nok: [192.168.122.11]\n\nTASK [Check if Apache service on CentOS 9.] ***************************************************************************************************************************************\nskipping: [192.168.122.92]\nok: [192.168.122.11]\n\nTASK [Check if Apache service on Ubuntu.] *****************************************************************************************************************************************\nskipping: [192.168.122.11]\nok: [192.168.122.92] => {\n    \"msg\": \"Apache service is present\"\n}\n\nPLAY RECAP ************************************************************************************************************************************************************************\n192.168.122.11             : ok=4    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   \n192.168.122.92             : ok=4    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 \n<\/code><\/pre>\n\n\n\n<p>And there you go.<\/p>\n\n\n\n<p>That marks the end of our tutorial on how to install and setup Ansible on Ubuntu 20.04. We hope this was informative. Enjoy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"further-reading\">Further Reading<\/h3>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_getting_started.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Getting Started with Ansible<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/?s=ansible\" target=\"_blank\" rel=\"noreferrer noopener\">Ansible tutorials<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we are going to learn how to install Ansible on Ubuntu 24.04. Ansible is a simple agentless IT automation tool. It handles<\/p>\n","protected":false},"author":10,"featured_media":15512,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_lock_modified_date":false,"footnotes":""},"categories":[121,1110,992,1722],"tags":[7448,7450,7449],"class_list":["post-22176","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-howtos","category-automate-system-tasks","category-automation","category-automation-2","tag-install-ansible-ubuntu-24-04","tag-installing-ansible-ubuntu-24-04","tag-ubuntu-24-04-ansible","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50","resize-featured-image"],"_links":{"self":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/22176"}],"collection":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/comments?post=22176"}],"version-history":[{"count":9,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/22176\/revisions"}],"predecessor-version":[{"id":22185,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/22176\/revisions\/22185"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/media\/15512"}],"wp:attachment":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/media?parent=22176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/categories?post=22176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/tags?post=22176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}