惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
博客园 - Franky
V
V2EX
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
T
The Blog of Author Tim Ferriss
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Jina AI
Jina AI
博客园 - 叶小钗
F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
About on SuperTechFans
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Last Week in AI
Last Week in AI
D
Docker
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Automating Windows Server Setup with Ansible: My DevOps J...
Sirisharaju · 2026-05-12 · via DEV Community

In my previous blog, I walked through how I automated Linux server setup using Ansible — SSH hardening, roles, and playbooks. If you haven't read that yet, check out Part 1 here.
In this post, I'll focus entirely on the Windows side — how I configured WinRM, built a reusable Windows role, and tied everything together into one master playbook that manages both Linux and Windows servers.

Windows Automation Feels Different at First
When I first tried to automate Windows servers with Ansible, it didn't feel anything like Linux. On Linux, Ansible just connects over SSH and you're off. Windows doesn't work that way.

A few things that caught my attention early on:

  • Windows uses WinRM instead of SSH — that's how Ansible communicates with it
  • Fresh Windows servers don't have WinRM enabled — I had to manually turn it on the first time
  • The modules are completely different — no apt, no service — everything goes through the ansible.windows collection
  • Once I got my head around these differences, the rest came together pretty smoothly.

**First Thing — Bootstrap WinRM (Just Once)
Before Ansible can do anything on a Windows server, WinRM needs to be enabled. I ran this PowerShell script once on each new Windows machine — after that, Ansible handles everything:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file

Adding Windows Hosts to the Inventory
I added the Windows servers into the same inventory file I was already using for Linux. The connection settings are different but the structure stays clean:

all:
children:
linux_servers:
hosts:
linux-01:
ansible_host: 10.0.1.10
ansible_user: ec2-user
ansible_ssh_private_key_file: ~/.ssh/id_rsa
windows_servers:
hosts:
win-01:
ansible_host: 10.0.2.10
ansible_user: Administrator
ansible_password: "{{ vault_win_password }}"
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_port: 5985

The Windows password is vaulted using ansible-vault — I never put credentials in plain text. That's just a habit I've built early on and I'd recommend everyone do the same.

Building the Windows Role
I kept the same role-based structure I used for Linux. Here's how the Windows role looks:

roles/
windows_setup/
├── tasks/main.yml
└── defaults/main.yml

roles/windows_setup/defaults/main.yml


  • name: Ensure WinRM service is running and set to auto start
    ansible.windows.win_service:
    name: WinRM
    state: started
    start_mode: auto

  • name: Disable unencrypted WinRM traffic
    ansible.windows.win_shell: |
    winrm set winrm/config/service '@{AllowUnencrypted="false"}'

  • name: Configure Windows Firewall to allow WinRM
    ansible.windows.win_firewall_rule:
    name: WinRM HTTP
    localport: "{{ winrm_port }}"
    action: allow
    direction: in
    protocol: tcp
    state: present
    enabled: true

  • name: Check for available Windows Security Updates
    ansible.windows.win_updates:
    category_names:

    • SecurityUpdates state: searched register: update_result
  • name: Display available updates

    ansible.builtin.debug:

    msg: "{{ update_result.updates | length }} security update(s) available"

The Windows Playbook


  • name: Configure Windows Servers hosts: windows_servers roles:
    • windows_setup

One thing I noticed here — there's no become: true like I used on Linux. Windows doesn't use sudo. The Administrator account takes care of privilege escalation directly.

Bringing It All Together — site.yml
This is the part I enjoyed the most. One playbook, one command, both Linux and Windows configured together:


  • import_playbook: playbooks/linux_setup.yml
  • import_playbook: playbooks/windows_setup.yml

And to run everything:
ansible-playbook site.yml -i inventory/hosts.yml --ask-vault-pass

That's it. Ansible runs through Linux first, then Windows — clean and consistent every single time.

ansible windows_servers -i inventory/hosts.yml -m ansible.windows.win_ping

If I get pong back, I know I'm good to go.
WinRM transport depends on your environment. I used ntlm since my servers weren't in a domain. If you're working in an Active Directory setup, kerberos is the better and more secure option.
Don't mix Linux and Windows modules. Early on I made the mistake of trying to use a Linux module on a Windows host — it fails and the error isn't always obvious. Stick to ansible.windows.* for everything Windows-related.

What Changed After This
Before this setup, configuring a new Windows server meant RDP-ing in, clicking through settings, and hoping I didn't miss anything. Now I just add the host to the inventory and run the playbook. Same result every time, no matter how many servers I'm dealing with.
Combined with Part 1, I now have a single automation setup managing both Linux and Windows from one place — and it's honestly one of the most satisfying things I've built so far in my DevOps journey.

Coming Up in Part 3
I'm planning to cover:

User management across Linux and Windows
Scheduling automated patching
Plugging Ansible into a CI/CD pipeline

Drop your questions or thoughts in the comments — always happy to discuss!
— Sireesha