Ansible Tutorial for Beginners: Playbook & Commands

โšก Smart Summary

Ansible is an open source, agentless automation engine that configures servers over SSH, runs ad-hoc commands, and orchestrates complex deployments through YAML playbooks, roles, and reusable templates across Linux and Windows infrastructure.

  • ๐Ÿงฉ Agentless Architecture: Ansible connects to clients over SSH and pushes modules, so no agent software has to be installed on the managed nodes.
  • ๐Ÿ“ฅ Installation: Set up Ansible on the control node with yum and EPEL on CentOS or RHEL, or with apt and the PPA on Ubuntu or Debian.
  • โšก Ad-hoc Commands: Run one-off tasks such as ping, copy, or yum across an inventory using the ansible -m module syntax.
  • ๐Ÿ“œ Playbooks: Describe the desired state in YAML playbooks that group plays, tasks, and modules to configure many servers consistently.
  • ๐Ÿงฑ Roles and Templates: Split large playbooks into reusable roles created with ansible-galaxy, and render configuration files with Jinja2 templates.
  • ๐Ÿ” Handlers and Facts: Trigger handlers through notifiers on change, and use gather_facts variables for conditional, repeatable automation.
  • ๐ŸŽฏ Case Study: A single p4.yml playbook can run the selinux, httpd, and resolver roles across all hosts, each controlled by a tag.

Ansible tutorial for beginners covering installation, ad-hoc commands, playbooks, roles, and templates

Ansible is one of the most widely adopted open source automation tools in modern DevOps, valued for its agentless design and its simple, readable configuration files. This Ansible tutorial for beginners explains what Ansible is, how to install it, and how to use ad-hoc commands, playbooks, roles, and templates through practical examples.

What is Ansible?

Ansible is an open source automation and orchestration tool for software provisioning, configuration management, and software deployment. It configures Unix-like systems and Windows systems alike, providing infrastructure as code through its own declarative language. Ansible is often compared with agent-based tools such as Puppet.

Ansible is popular for its simple installation, its easy client connectivity, and its agentless design. It connects to clients over SSH, so no special agent is required on the client side. Ansible pushes modules to each client, the modules run locally, and their output is returned to the Ansible server.

Because it relies on SSH, Ansible connects to clients easily using SSH keys, which simplifies the whole process. Client details such as hostnames or IP addresses and SSH ports are stored in files called inventory files. Once you create and populate an inventory file, Ansible can use it.

Why use Ansible?

Here are some important benefits of using Ansible:

  • One of the most significant advantages of Ansible is that it is free for everyone to use.
  • It does not require special system administrator skills to install and use, and the official documentation is very comprehensive.
  • Its modularity across plugins, modules, inventories, and playbooks makes Ansible an excellent companion for orchestrating large environments.
  • Ansible is lightweight and consistent, with no constraints on the operating system or the underlying hardware.
  • It is very secure thanks to its agentless design and its use of OpenSSH security features.
  • Ansible has a smooth learning curve, supported by thorough documentation and an easy-to-learn structure and configuration.

These strengths, especially when weighed against other alternatives to Ansible, help explain its rapid adoption. Before installing it, it helps to understand how the project evolved.

History of Ansible

Here are the important landmarks in the history of Ansible:

  • The Ansible project began in February 2012. It was first developed by Michael DeHaan, the creator of Cobbler and Func (Fedora Unified Network Controller).
  • Initially called AnsibleWorks Inc, the company funding Ansible was acquired by RedHat in 2015 and later, along with RedHat, moved under the IBM umbrella.
  • Today, Ansible is included in distributions such as Fedora Linux, RHEL, CentOS, and Oracle Linux.

Important terms used in Ansible

The following terms appear throughout this Ansible tutorial and are worth knowing before you start:

Ansible server

The machine where Ansible is installed and from which all tasks and playbooks are run.

Module

A module is a command, or a set of similar Ansible commands, meant to be executed on the client side.

Task

A task is a section that consists of a single procedure to be completed.

Role

A way of organizing tasks and related files so they can be called later in a playbook.

Fact

Information fetched from the client system global variables through the gather_facts operation.

Inventory

A file containing data about the Ansible client servers. It is defined in later examples as the hosts file.

Play

The execution of a playbook.

Handler

A task that is called only when a notifier is present.

Notifier

A section attributed to a task that calls a handler if the output changes.

Tag

A name set on a task that can be used later to run just that specific task or group of tasks.

Ansible Installation in Linux

Once you have weighed your options and decided to adopt Ansible, the next step is to install it on your system. The following short walkthrough covers installation on the most popular Linux distributions.

Install Ansible on Centos/RedHat systems

Step 1) Install the EPEL repo.

[root@ansible-server ~]# sudo yum install epel-release

Step 2) Install the ansible package.

[root@ansible-server ~]# sudo  yum install -y ansible

Install Ansible on Centos/RedHat systems

Install ansible on Ubuntu/Debian systems

Step 1) Perform an update to the packages.

$ sudo apt update

Step 2) Install the software-properties-common package.

$ sudo apt install software-properties-common

Step 3) Install the ansible personal package archive.

$ sudo apt-add-repository ppa:ansible/ansible

Step 4) Install ansible.

$ sudo apt update
$ sudo apt install ansible

Ansible ad-hoc commands

One of the simplest ways to use Ansible is through ad-hoc commands. These are useful when you want to issue a command on a single server or on a group of servers. Ad-hoc commands are not stored for future use, but they are a fast way to interact with the servers you choose.

For this Ansible tutorial, a simple two-server hosts file is configured, containing host1 and host2.

You can confirm that the hosts are reachable from the Ansible server by issuing a ping command on all hosts.

[root@ansible-server test_ansible]# ansible -i hosts all -m ping
host1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
host2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Ansible ad-hoc Commands

Explanation:

  1. Status of the command, in this case, SUCCESS
  2. Host on which the command ran
  3. The command issued via the -m parameter, in this case, ping
  4. With the -i parameter, you can point to the hosts file.

You can also issue the same command on a single host when needed.

[root@ansible-server test_ansible]# ansible -i hosts all -m ping --limit host2
host2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Ansible ad-hoc Commands

Explanation:

  1. Limit parameter can be used to issue commands only on specific hosts in the host’s file
  2. Name of the host as defined in the inventory file

If you need to copy a file to multiple destinations quickly, use the copy module, which relies on SCP. The command and its output look like the following:

[root@ansible-server test_ansible]# ansible -i hosts all -m copy -a "src=/root/test_ansible/testfile dest=/tmp/testfile"
host1 | SUCCESS => {
    "changed": true,
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "dest": "/tmp/testfile",
    "gid": 0,
    "group": "root",
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e",
    "mode": "0644",
    "owner": "root",
    "size": 0,
    "src": "/root/.ansible/tmp/ansible-tmp-1562216392.43-256741011164877/source",
    "state": "file",
    "uid": 0
}
host2 | SUCCESS => {
    "changed": true,
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "dest": "/tmp/testfile",
    "gid": 0,
    "group": "root",
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e",
    "mode": "0644",
    "owner": "root",
    "size": 0,
    "src": "/root/.ansible/tmp/ansible-tmp-1562216392.6-280302911361278/source",
    "state": "file",
    "uid": 0
}

Ansible ad-hoc Commands

Explanation:

  1. Copy module defined
  2. Module arguments, in this case, are source absolute path and destination absolute path.
  3. Ansible command output reflecting the success of the copy command and other details like the sha1 or md5 checksums for file integrity check and metadata like owner, size, or permissions.It is effortless to have a package installed on a bunch of servers. Ansible has several modules that interact with used installers, like yum, apt, dnf, etc.

In the next example, you will install a package with the yum module on two CentOS hosts.

[root@ansible-server test_ansible]# ansible -i hosts all -m yum -a 'name=ncdu state=present'
host1 | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [


"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirror.netsite.dk\n * elrepo: mirrors.xservers.ro\n * epel: fedora.mirrors.telekom.ro\n * extras: centos.mirrors.telekom.ro\n * remi-php70: remi.schlundtech.de\n * remi-safe: remi.schlundtech.de\n * updates: centos.mirror.iphh.net\nResolving Dependencies\n--> Running transaction check\n---> Package ncdu.x86_64 0:1.14-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n========================================================================\n Package         Arch              Version                Repository       Size\n========================================================================\nInstalling:\n ncdu            x86_64            1.14-1.el7             epel             51 k\n\nTransaction Summary\n========================================================================\nInstall  1 Package\n\nTotal download size: 51 k\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : ncdu-1.14-1.el7.x86_64                                       1/1 \n  Verifying  : ncdu-1.14-1.el7.x86_64                                       1/1 \n\nInstalled:\n  ncdu.x86_64 0:1.14-1.el7                                                      \n\nComplete!\n"
    ]
}
host2 | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirror.netsite.dk\n * elrepo: mirrors.leadhosts.com\n * epel: mirrors.nav.ro\n * extras: centos.mirrors.telekom.ro\n * remi-php70: mirrors.uni-ruse.bg\n * remi-safe: mirrors.uni-ruse.bg\n * updates: centos.mirror.iphh.net\nResolving Dependencies\n--> Running transaction check\n---> Package ncdu.x86_64 0:1.14-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n========================================================================\n Package         Arch              Version                Repository       Size\n========================================================================\nInstalling:\n ncdu            x86_64            1.14-1.el7             epel             51 k\n\nTransaction Summary\n========================================================================\nInstall  1 Package\n\nTotal download size: 51 k\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : ncdu-1.14-1.el7.x86_64                                       1/1 \n  Verifying  : ncdu-1.14-1.el7.x86_64                                       1/1 \n\nInstalled:\n  ncdu.x86_64 0:1.14-1.el7                                                      \n\nComplete!\n"
    ]
}

Ansible ad-hoc Commands

Explanation:

  1. Yum module is used in this example
  2. It defines the module arguments, and in this case, you will choose the name of the package and its state. If the state is absent, for example, the package will be searched and if found, removed
  3. When colored in yellow, you will see the output of the ansible command with the state changed, meaning in this case, that the package was found and installed.
  4. Status of the yum install command issued via ansible. In this case the package ncdu.x86_64 0:1.14-1.el7 was installed.

Of course, all of the yum installer options can be used through Ansible, including update, install, latest version, and remove.

In the example below, the same command is issued to remove the previously installed ncdu package.

[root@ansible-server test_ansible]# ansible -i hosts all -m yum -a 'name=ncdu state=absent'
host1 | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package ncdu.x86_64 0:1.14-1.el7 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n========================================================================\n Package         Arch              Version               Repository        Size\n========================================================================\nRemoving:\n ncdu            x86_64            1.14-1.el7            @epel             87 k\n\nTransaction Summary\n========================================================================\nRemove  1 Package\n\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Erasing    : ncdu-1.14-1.el7.x86_64                                       1/1 \n  Verifying  : ncdu-1.14-1.el7.x86_64                                       1/1 \n\nRemoved:\n  ncdu.x86_64 0:1.14-1.el7                                                      \n\nComplete!\n"
    ]
}
host2 | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package ncdu.x86_64 0:1.14-1.el7 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n========================================================================\n Package         Arch              Version               Repository        Size\n========================================================================\nRemoving:\n ncdu            x86_64            1.14-1.el7            @epel             87 k\n\nTransaction Summary\n========================================================================\nRemove  1 Package\n\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Erasing    : ncdu-1.14-1.el7.x86_64                                       1/1 \n  Verifying  : ncdu-1.14-1.el7.x86_64                                       1/1 \n\nRemoved:\n  ncdu.x86_64 0:1.14-1.el7                                                      \n\nComplete!\n"
    ]
}

Ansible ad-hoc Commands

Explanation:

  1. The output of the yum command shows that the package was removed.

Another essential Ansible feature is its ability to gather facts about a system. It collects hardware, software, and version information and stores each value in a variable that you can reuse later.

When you need detailed information about the systems that Ansible will modify, the setup module gathers these facts from the system variables.

Ansible ad-hoc Commands

Ansible Playbooks

Ansible Playbooks are the way to send commands to remote systems through scripts. Playbooks configure complex system environments and increase flexibility by running a single script against one or more systems. They behave more like a configuration language than a programming language.

Playbook commands use the YAML format, so little syntax is needed, but indentation must be respected. As the name suggests, a playbook is a collection of plays. Through a playbook, you can assign specific roles to some hosts and different roles to others, orchestrating many servers in one file.

Before continuing with the playbook examples, it helps to define a task. Tasks are the interface to Ansible modules for roles and playbooks.

Now, consider an Ansible playbook with one play that contains multiple tasks, as shown below:

---

- hosts: group1
  tasks:
  - name: Install lldpad package
    yum:
      name: lldpad
      state: latest
  - name: check lldpad service status
    service:
      name: lldpad
      state: started

Ansible Playbooks

In the playbook above, the group1 hosts in the hosts file are targeted for lldpad package installation using the yum module. The lldpad service created after installation is then started using the service module, which mostly interacts with the systemd ensemble.

Explanation:

  1. Group of hosts on which the playbook will run
  2. Yum module is used in this task for lldpad installation
  3. The service module is used to check if the service is up and running after installation

Each Ansible playbook works with an inventory file. The inventory file contains a list of servers divided into groups, giving better control over details such as the IP address and SSH port for each host.

The inventory file for this playbook example looks like the following. There are two groups, group1 and group2, each containing host1 and host2 respectively.

[group1]
host1 ansible_host=192.168.100.2 ansible_ssh_port=22
[group2]
host2 ansible_host=192.168.100.3 ansible_ssh_port=22

Ansible Playbooks

Explanation:

  1. Group name
  2. Hostname, with IP address and ssh port, in this case, the default one, 22.

The next Ansible playbook example contains two plays for two host groups. For the first group, group1, SELinux is enabled, and when it is enabled a message appears on the host screen.

For the second group, the httpd package is installed only if ansible_os_family is RedHat and ansible_system_vendor is HP.

ansible_os_family and ansible_system_vendor are variables gathered with the gather_facts option, and they can be used as in this conditional example.

---

- hosts: group1
  tasks:
  - name: Enable SELinux
    selinux:
      state: enabled
    when: ansible_os_family == 'Debian'
    register: enable_selinux

  - debug:
      Imsg: "Selinux Enabled. Please restart the server to apply changes."
    when: enable_selinux.changed == true

- hosts: group2
  tasks:
  - name: Install apache
    yum:
      name: httpd
      state: present
    when: ansible_system_vendor == 'HP' and ansible_os_family == 'RedHat'

Ansible Playbooks

Explanation:

  1. Example of the when clause, In this case, when OS type is Debian. The ansible_os_family variable is gathered via gather_facts functionality.
  2. The task output is registered for future use, with its name enable_selinux
  3. Another example of the when clause. In this case, a message will be displayed for the host user if the SELinux was indeed enabled before.
  4. Another example of the when clause consisting of two rules

Besides tasks, there are also special tasks called handlers. A handler must have a unique name throughout the playbook. Handlers work like a regular task, but a handler can be notified through a notifier.

If a handler is not notified during a playbook run, it does not run. However, if more than one task notifies a handler, it runs only once after all the tasks are finished.

In the example below, a specific task has a notify section that calls another task. If the output of the first task changes, a handler task is called. A common example is changing a configuration file and then restarting the affected service.

---

- hosts: group2
  tasks:
  - name: sshd config file modify port
    lineinfile:
     path: /etc/ssh/sshd_config
     regexp: 'Port 28675'
     line: '#Port 22'
    notify:
       - restart sshd
handlers
    - name: restart sshd
      service: sshd
        name: sshd
        state: restarted

In this case, if the first task, “sshd config file modify port”, changes, meaning the port is not already 28675, the port is modified and the task notifies the handler of the same name, which restarts the sshd service.

Ansible Playbooks

Explanation:

  1. Example of a notifier
  2. Example of a handler

Ansible Roles

When working with large playbooks, it is easier to split the tasks into roles. Roles also make it easier to reuse work later. A role is a collection of tasks that can be moved from one playbook to another and run independently, though only through a playbook file.

Roles are stored in separate directories and follow a specific directory structure.

[root@ansible-server test2]# tree
.
`-- role1
    |-- defaults
    |   `-- main.yml
    |-- handlers
    |   `-- main.yml
    |-- meta
    |   `-- main.yml
    |-- README.md
    |-- tasks
    |   `-- main.yml
    |-- tests
    |   |-- inventory
    |   `-- test.yml
    `-- vars
        `-- main.yml

7 directories, 8 files

The YAML file in the defaults directory holds the default variables used with the playbook. The handlers directory stores handlers, and the meta directory holds information about the author and role dependencies. The tasks directory contains the main YAML file for the role.

The tests directory contains a sample YAML playbook and a sample inventory file, and it is mostly used for testing before the actual role is created.

The vars directory contains the YAML file where all variables used by the role are defined. The templates and files directories hold the templates and files used by the tasks in the role.

To create the directory tree for a role, use the following command with the role name as the last parameter:

[root@ansible-server test2]# ansible-galaxy init role1

Ansible also works well with templates, and it uses Jinja2 as its templating language.

The next example shows what a basic Jinja2 template looks like and how to use it in a role.

At run time, depending for example on which datacenter your server is located in, you can select from several nameservers, each corresponding to a datacenter, using the variable resolver_ip_addresses.

{% for resolver in resolver_ip_addresses %}
nameserver {{ resolver }}
{% endfor %}

options timeout:1
options attempts:5
options rotate

In this example, the playbook directory defines several variables, including resolver_ip_addresses, with different values depending on the datacenter.

- name: Set resolver for server
  template:
    src: dns.j2
    dest: /etc/resolv.conf
    group: root
    owner: root
    mode: "0644"
    tag: resolver

Ansible Roles

Explanation:

  1. Name of the template to be used. Template is located in templates dir in the role path
  2. Destination path of the filename to be replaced with the template, on the client-side.
  3. Permissions of the destination file

Role tasks can also have a tag field with an assigned name. More than one task can share the same tag, and when you run a playbook you can specify a tag so that only the tagged tasks are executed.

Ansible Case Study

In this section, we analyze a case study of an essential Ansible playbook that has three roles. The goal is to give a practical example of the concepts covered so far. Some earlier examples from this tutorial are adapted and reused in this playbook.

Below is the directory structure of the playbook. The YAML file used is p4.yml.

[root@ansible-server test_ansible]# ls -lrth
total 16K
-rw-r--r--. 1 root root   0 Jul  3 10:13 testfile
-rw-r--r--. 1 root root 203 Jul  3 13:30 p1.yml
-rw-r--r--. 1 root root 125 Jul  3 15:00 hosts
-rw-r--r--. 1 root root 488 Jul  3 16:40 p2.yml
-rw-r--r--. 1 root root 188 Jul  4 17:33 p4.yml
drwxr-xr-x. 5 root root  47 Jul  4 17:35 roles
[root@ansible-server test_ansible]# cd roles
[root@ansible-server roles]# ls -lrth
total 12K
drwxr-xr-x. 9 root root 4.0K Jul  4 12:52 httpd
drwxr-xr-x. 9 root root 4.0K Jul  4 13:55 selinux
drwxr-xr-x. 9 root root 4.0K Jul  4 16:54 resolver

The playbook has three roles. The resolver role sets a specific nameserver on the servers by copying a file to the /etc/resolv.conf destination. The httpd role installs the httpd package with the yum module, and the third role enables SELinux and notifies the logged-in user to reboot the system. Each role was created with the ansible-galaxy command.

Resolver role, main.yml task:

Ansible Case Study

Httpd role, main.yml task:

Ansible Case Study

Selinux role, main.yml task:

Ansible Case Study

Below is the p4.yml playbook. It runs on all hosts unless otherwise specified on the command line, runs as the root user on port 22 (SSH), gathers facts before running the roles, and runs all three roles. Each role can be run independently by specifying its tag on the ansible-playbook command line with the โ€“t parameter.

---

- hosts: all
  user: root
  port: 22
  gather_facts: True
  roles:
    - { role: selinux, tags: selinux }
    - { role: httpd, tags: httpd }
    - { role: resolver, tags: resolver }

You can then run the p4.yml playbook on the two hosts and interpret the output. The same command can be run with the โ€“check parameter for a dry run, and with the -k parameter when you want to use password authentication.

Ansible Case Study

Explanation:

  1. Ansible-playbook command that runs p4.yml
  2. Playbook skipsSELinux role because it is already enabled.
  3. Ansible found that httpd package is already installed, so it returns ok.
  4. Resolver was set, and role resolver got status changed.

Ansible Commands Cheat Sheet

Install EPEL repo on Centos/RHEL systems

[root@ansible-server ~]# sudo yum install epel-release

Install ansible package on Centos/RHEL systems

[root@ansible-server ~]# sudo  yum install -y ansible

Perform an update to the packages on Debian/Ubuntu systems

$ sudo apt update

Install the software-properties-common package on Debian/Ubuntu systems

$ sudo apt install software-properties-common

Install ansible personal package archive on Debian/Ubuntu systems

$ sudo apt-add-repository ppa:ansible/ansible

Install ansible on Debian/Ubuntu systems

$ sudo apt update
$ sudo apt install ansible

Issue a ping command on all servers defined in the inventory file named hosts

[root@ansible-server test_ansible]# ansible -i hosts all -m ping

Issue a ping command only on host2

[root@ansible-server test_ansible]# ansible -i hosts all -m ping --limit host2

Copy the file “testfile” on all hosts in the inventory file

[root@ansible-server test_ansible]# ansible -i hosts all -m copy -a "src=/root/test_ansible/testfile dest=/tmp/testfile"

Install ncdu package on all hosts

[root@ansible-server test_ansible]# ansible -i hosts all -m yum -a 'name=ncdu state=present'

Remove ncdu package on all hosts

[root@ansible-server test_ansible]# ansible -i hosts all -m yum -a 'name=ncdu state=absent'

Build the directory structure for role named role1.

[root@ansible-server test2]# ansible-galaxy init role1

Dry-run p4.yml playbook

[root@ansible-server test_ansible]# ansible-playbook -i hosts p4.yml --check

Run p4.yml playbook with password authentication for all hosts

[root@ansible-server test_ansible]# ansible-playbook -i hosts p4.yml -k

FAQs

Yes. Ansible is agentless, so no software runs on the managed nodes. It connects over SSH, or WinRM for Windows, and pushes small modules that execute on the target and are then removed. Only the control node needs Ansible and Python installed.

Ansible playbooks are written in YAML, which is human-readable and depends on indentation rather than braces. Templates use the Jinja2 templating language, while facts and variables let one playbook adapt to many hosts. No general-purpose programming background is required to begin.

Ansible is agentless and push-based, sending changes over SSH, while Puppet and Chef are usually agent-based and pull-based. Ansible uses YAML, whereas Chef uses Ruby and Puppet uses its own DSL. Many teams choose Ansible for its lower learning curve.

Yes. Ansible is free and open source under the GNU GPL, maintained by Red Hat and a large community. The core engine and thousands of modules cost nothing. Red Hat also sells Ansible Automation Platform, a paid product that adds a GUI, role-based access, and support.

Yes. Besides Linux and Unix hosts reached over SSH, Ansible manages Windows nodes through WinRM using dedicated Windows modules. It can install packages, edit the registry, manage services, and run PowerShell, so mixed Linux and Windows fleets are automated from one control node.

Ansible Galaxy is a public hub for sharing and downloading community roles and collections. The ansible-galaxy command scaffolds a role’s directory structure and installs published roles, so you can reuse tested automation instead of writing every playbook from scratch.

AI assistants can draft YAML playbooks from a plain-language request, explain unfamiliar modules, and suggest fixes for failed tasks or syntax errors. They can also convert shell scripts into idempotent tasks. Always review generated playbooks for correct module names and idempotency before running them.

Yes. GitHub Copilot autocompletes playbook tasks, inventory entries, and Jinja2 templates from a short comment or file name. Treat its output as a starting point, and check indentation, module parameters, and variable names, because generated YAML can reference outdated syntax or nonexistent modules.

Summarize this post with: