Ansible is a Python application that was created as a low-overhead, sensible configuration management solution. You can use Ansible to prevent configuration drift and enforce compliance in both local and cloud environments. One of Ansible's biggest advantages is its agentless architecture.
The machine you use to perform your configuration management tasks is called the control node; this machine must run Linux (WSL on Windows is fine) and have Python installed. Your managed nodes are recorded in a simple INI or YAML file called inventory. I recommend you use Visual Studio Code for Ansible development, which is excellent, and it's also simple to integrate VS Code with WSL.
The network communications between the Ansible control and management nodes take place either with Secure Shell (SSH) or Windows Remote Management (WinRM). So, you don't have to worry about opening any nonstandard ports in your network infrastructure.
You can do administration by running the Ansible command-line interface (CLI) interactively, but the deeper power of Ansible is evident when you encapsulate your configuration management tasks in YAML playbooks. You can even aggregate multi-playbook solutions into Ansible roles and share them with the community through the Ansible Galaxy.
You can orchestrate all of your enterprise configuration management from your workstation. But isn't there a central "command and control" available for Ansible?" The answer here is "Yes," and it's called the Red Hat Ansible Automation Platform (formerly called Ansible Tower).
The Ansible Automation Platform is a paid product that gives administrators a centralized REST API and web portal from which to control your nodes.
Examine the lab environment
Take a look at the screenshot below while I walk you through my simple Windows lab environment. I've got two Windows Server 2022 hosts: dc1 is my Active Directory domain controller acting as my Ansible control node, and mem1 is a domain member server acting as a managed node.
Client–server network communications take place on either TCP 5985 (HTTP) or TCP 5986 (HTTPS) via WinRM PowerShell remoting.
The control node has Python 3 and Ansible installed under Windows Subsystem for Linux (WSL). While Linux-managed nodes need to have Python installed, Windows nodes are different—they need only WinRM PowerShell remoting enabled.
Install Ansible on Windows
As mentioned previously, the Ansible server bits run only on Linux. Thus, you'll need to set up WSL2 on your Windows Server control node before you can install Ansible. It's really only one command to install WSL2 with Ubuntu:
Once WSL is ready, open a WSL command prompt, and run the following Terminal commands to install Ansible on Windows. The Ansible docs are a required reference for you as well.
sudo apt update sudo apt install software-properties-common sudo add-apt-repository --yes --update ppa:ansible/ansible sudo apt install ansible -y
You can verify Ansible installation completed successfully by running ansible –-version; I show you my output in the screenshot below.
Edit the configuration file
Take special note of the location of the default Ansible configuration file: /etc/ansible/ansible.cfg. Ansible stores all its configuration properties in this INI-format text file. While this is the global location, you can override its values by specifying a configuration file in another path.
While we're on the subject, go ahead and open the config file with a text editor such as nano:
sudo nano /etc/ansible/ansible.cfg
Add the following text block to the top of the file:
Create the inventory file
We need to add dc1 and mem1 to our Ansible inventory file so that we can include these machines in our Ansible configuration management tasks. Run these commands to create the file and open it in nano:
sudo touch /etc/ansible/hosts sudo nano /etc/ansible/hosts
Next, add the following text to the file, save your work, and exit nano:
[control] dc1 ansible_host=10.0.2.15 [infra] mem1 ansible_host=10.0.2.16 [infra:vars] ansible_user=administrator ansible_password=P@$$w0rd143! ansible_port=5986 ansible_connection=winrm ansible_winrm_transport=basic ansible_winrm_server_cert_validation=ignore
There's a lot going on in that INI-format inventory file. Let me explain each part:
- [control], [infra]: These are host groups. We put our controller node in a group called control and our managed node in a group called infra.
- ansible_host: This is an Ansible built-in variable that tells Ansible the DNS host name or IP address to use when communicating with that node. It's optional, but a nice way to use a short alias name for a node (think of how many nonintuitive DNS names you use in your environment).
- [infra:vars]: Variables operate in Ansible like they do in any programming language: reusable key:value pairs. Here, we define variables that instruct Ansible to use WinRM as our transport and the built-in local Administrator account and password as connection credentials.
NOTE: Obviously, you never want to expose passwords in plain text in any file. Ansible presents a number of ways to protect sensitive information. These include encrypting the relevant files, using Ansible Vault, or a third-party secrets solution. This subject is too broad to be included in this introductory tutorial.
Enable PowerShell remoting
Ansible provides a PowerShell script that simplifies the WinRM listener configuration. You'll want to run the commands below on both your control node and your management node.
Test connectivity with ad hoc commands
Now let's undertake some actual configuration management with Ansible. We'll work from the control node in your WSL prompt from now on.
When you install Ansible, you get a library of built-in modules each of which covers a particular product or technology. The Windows Ansible modules all have the prefix win_. Run the ansible-doc Ansible CLI command to see all the available built-in modules:
ansible-doc -l | grep 'win'
Some of the most common built-in Windows Ansible modules include the following:
- win_domain_controller: Manage both domain controller and member server state for target hosts
- win_file: Create or remove files and folders
- win_ping: Test network connectivity
- win_regedit: Add, change, and remove Registry keys and values
- win_setup: Gather facts about target hosts
- win_shell: Execute shell or PowerShell commands on target hosts
- win_whoami: Get information about the current user and target host
The command below is the de facto connectivity check between your Ansible control node and the managed nodes. In this example, we target the inventory's infra group; you can specify the all keyword to target all nodes in the inventory.
ansible infra -m win_ping
Ansible "facts" refer to node metadata. You can easily retrieve all such facts by invoking the built-in win_whoami module:
ansible infra -m win_whoami
Run a playbook
Running Ansible CLI commands in an ad hoc fashion is convenient when you're in a pinch. However, you want to focus the bulk of your configuration management on playbooks.
In the following example, I create a new file called apache.yaml to install the Apache web server:
--- - name: Installing Apache MSI hosts: win tasks: - name: Download the Apache installer win_get_url: url: https://archive.apache.org/dist/httpd/binaries/win32/httpd-2.2.25-win32-x86-no_ssl.msi dest: C:\httpd-2.2.25-win32-x86-no_ssl.msi - name: Install MSI win_package: path: C:\ansible_examples\httpd-2.2.25-win32-x86-no_ssl.msi state: present
Now beware: YAML is not only case-sensitive but VERY finicky about indentation. Some brief explanatory notes about the Ansible playbook structure:
- hosts: Specify inventory groups, inventory hosts, or all or ungrouped keywords to target hosts
- tasks: Each play in a playbook consists of one or more tasks, which are atomic units of work
- win_get_url, win_package: These are two built-in modules that download the Apache web server software installer and then install it
Run the ansible-playbook command to run the playbook:
Ansible playbooks are idempotent, which means you can run them over and over again, and only changes you make to the file will be applied to the target nodes.
Use the built-in win_stat module to verify that the Apache software directory is present on the target node:
ansible infra -m win_stat -a "path='C:\Program Files (x86)\Apache Software Foundation\Apache2.2'"
Notice that the stat: dictionary contains an "exists": true key/value pair for the Apache web server installation directory.
I hope you have a clearer idea of what Ansible is and how it works in Windows Server environments. To be sure, we've only scratched the surface of this broad and deep topic. Let me leave you with some Ansible doc links you may want to study next.