So maybe you’ve heard of Ansible, but you have a bunch of windows servers and don’t know how to get started, or maybe you’ve even got an Ansible server set up and are already managing linux servers but don’t know how to get your Windows servers attached too. This guide is for you! I’ll show you how to set up a minimal Ansible install on an Ubuntu server and set up a Windows host to be managed.
One thing of note is that this didn’t work until I applied all the updates to my windows server. The SSH connection worked, but Ansible would just hang forever when connecting to that host.
WinRM vs SSH
In the past the only way to manage a Windows machine with Ansible was to use WinRM. Frankly the documentation for that scares me. The good news is that it’s now possible to run OpenSSH on windows, and experimental support for managing windows hosts over SSH was added in Ansible 2.8. Now we can manage Windows hosts in a way that is familiar to linux admins and is relatively easy to set up.
Part 1 – Ubuntu Setup
Install Ansible on Ubuntu
Installing Ansible on Ubuntu is easy. Just run this on your Ubuntu machine.
sudo apt install -y ansible
That’s it! Ansible is ready to use on the CLI. You can verify with the following command. On my Ubuntu 20.04 server I got Ansible 2.9.6.
ansible --version
Generate SSH Key
I like to use SSH keys so ansible can connect to my remote hosts without needing a password. If you don’t already have an SSH key pair set up, you can create one with the following command.
ssh-keygen
I just accept all the defaults, including no password, but you can customize as desired. Copy your public key and get it over to your windows machine somehow. I just copy it out of my SSH session to my ubuntu box and paste it into notepad on the windows box.
cat ~/.ssh/id_rsa.pub
Part 2 – Windows Setup
Installing Chocolatey
This isn’t strictly required, but for my purposes Chocolatey seems like it might be useful to install and update software, and it can install OpenSSH for us. You can install Chocolatey by pasting the following code snippet into an elevated Powershell prompt. This comes directly from their website here: https://chocolatey.org/install#individual
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
Installing OpenSSH
Once Chocolatey is installed, we can install OpenSSH using the following command.
choco install -y --package-parameters=/SSHServerFeature openssh
If you prefer not to use Chocolatey, you can follow these instructions from Microsoft to install OpenSSH manually.
Configure OpenSSH
I want to use SSH key auth so Ansible can connect without needing a password. On a linux machine I’d simply add the Ansible user’s public key to the authorized_keys file on my target machine.
We can do the same on Windows, but first we need to change the OpenSSH config to look in the correct place. By default, the authorized_keys files for administrator accounts are not in the expected location. You can read more about this here.
To restore the expected behaviour, edit C:\ProgramData\ssh\sshd_config and remove or comment out the following two lines at the bottom of the file. You can edit this file using notepad (run as administrator).
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
Restart the sshd service.
net stop sshd
net start sshd
Enable SSH with the public key
You’ll need that public key you copied earlier from your ubuntu box.
First, we need to create a folder for the local user ssh config. In a command prompt in your home directory (such as C:\Users\Administrator) run the following command.
mkdir .ssh
Next create your authorized_keys file if it doesn’t exist
type nul >>.ssh\authorized_keys
And open it for editing
notepad .ssh\authorized_keys
Paste your ubuntu public key into this new file and save it.
Finally, we need to modify the permissions of this file to remove Everyone from the file or else sshd will ignore it.
icacls authorized_keys /remove Everyone
Test the SSH connection
From your ubuntu box you should be able to connect to your windows box using SSH!
ssh Administrator@IP_OF_WINDOWS_SVR
If your account is a domain user, enter the username in this format
ssh Administrator@domain.example.com@IP_OF_WINDOWS_SVR
Part 3 – Ansible
Ansible config in a nutshell? We need at minimum an inventory file, and possibly a playbook. The inventory file tells Ansible where the hosts it’s going to manage are located and how to connect to them. The playbook lets you define a list of tasks to run on the hosts in the inventory.
Inventory
On your ubuntu box, create a file called inventory.yml and configure it like so
---
all:
hosts:
my_windows_server:
ansible_shell_type: cmd
ansible_host: IP_OF_WINDOWS_SVR
ansible_user: Administrator
If your account is in a domain, be sure to add @domain.example.com to your username.
Test your connection by running the following command
ansible -i inventory.yml -m win_ping my_windows_server
You should get something like the following output
my_windows_server | SUCCESS => {
"changed": false,
"ping": "pong"
}
Playbook
Rather than manually running a module with the ansible command, we can string together as many tasks as we like in a playbook. Here’s an example playbook that sets the timezone and opens the RDP port. I’ll call it playbook.yml
---
- hosts: all
tasks:
- name: Set timezone to 'Central Standard Time' (GMT-06:00)
win_timezone:
timezone: Central Standard Time
- name: Firewall rule to allow RDP on TCP port 3389
win_firewall_rule:
name: Remote Desktop
localport: 3389
action: allow
direction: in
protocol: tcp
profiles: [domain, private]
state: present
enabled: yes
You can execute the playbook with the following command
ansible-playbook -i inventory.yml playbook.yml
If everything goes to plan you should see output like this
PLAY [all] *************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************
ok: [my_windows_server]
TASK [Set timezone to 'Central Standard Time' (GMT-06:00)] *************************************************************
changed: [my_windows_server]
TASK [Firewall rule to allow RDP on TCP port 3389] *********************************************************************
changed: [my_windows_server]
PLAY RECAP *************************************************************************************************************
my_windows_server : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conclusion
If you made it this far then you should have a minimum viable ansible install capable of managing windows hosts. There is so much more to explore with Ansible, and this guide doesn’t even scratch the surface, but hopefully it helps you get started on your journey.
For further reading on the available windows modules check out the offical documentation here.